스트림

Java

목록 보기
21/26
post-thumbnail

1. 스트림

  • 다양한 데이터 소스(ex 컬렉션, 배열 ...)를 표준화된 방법으로 다루기 위한 것
  • List, Set, Map 등을 통해서 스트림을 만들 수 있어요.
  • 중간 연산(n번 할 수 있음) + 최종 연산(딱 1번 할 수 있어요)

    Stream<T> Collection.stream()
  • 모든 종류의 컬렉션을 스트림으로 이렇게 수비게 반환할 수 있어요.
Stream<Integer> intStram = list.stream();
Stream<String> strstream = Stream.of(mew String[] {"1", "b", "c"}); //배열
Stream<Integer> evenStream = Stream.iterate(0,n->n+2);	//0,2,4,6,...
Stream<double> randomStream = Stream.generate(Math::random);	//람다식
InteStream int Stream = new Random().ints(5);	//난수 스트림(크기가 5)

1-1. Stream = 데이터가 흘러가는 천

  • 스트림 : 데이터의 연속적인 흐름
  • 스트림이 제공하는 기능 : 중간 연산과 최종 연산
  1. 스트림 만들기
  2. 중간 연산
  3. 최종 연산
  • 중간 연산 : 연산결과가 스트림인 연산. 반복적으로 사용 가능
  • 최종 연산 : 연산결과가 스트림이 아닌 연산. 단 한번만 적용 가능(쓰트림의 요소를 소모)
1. 작업 할 배열을 만든다
String[] strArr = {"dd","aaa","CC","cc","b"};
2. 스트림을 만든다
Stream<String> stream = Stream.of(strArr);
3. 중간연산 n번
Stream<String> filteredStream = stream.fileter();
Stream<String> distincedStream = stream.distinct();
Stream<String> sortedStream = stream.sort();
Stream<String> limitedStream = stream.limit(5);
4. 최종 연산(요소 개수 세기)
int total = stream.count();

2. 스트림의 특징

2-1. 변경 불가

  • 스트림은 데이터 소스로부터 데이터를 읽기만 할 뿐 변경하지 않는다.
List<Integer> list = Arrays.asList(3,1,5,4,2);
List<Integer> sortedList = list.stream().sorted(); //리스트를 정렬해서
			.							.collect(Collectors.toList()); 	//새로운 List에 저장
System.out.println(list);	//[3,1,5,4,2]
System.out.println(sortedList);	//[1,2,3,4,5]

(자세한 건 신경쓰지마세요)

2-2. 스트림은 Iterator처럼 일회용이다.

  • 필요하면 다시 스트림을 생성해야 함
strStream.forEach(System.out.::println);	//모든 요소를 화면에 출력
int numOfstr = strrStream.count();		//에러. 스트림 이미 닫힘.

2-3. 최종 연산 전까지 중간연산이 수행되지 않는다.

  • 지연된 연산을 수행한다.
IntStream intStream = new Random().ints(1,46);	//무한스트림
intStream.distinct().list(6).sorted()	//중간연산
.forEach(i -> System.out.println(i+","));	//최종연산

무한인데 중복제거가 됩니다. 중간 연산으로 중복 제거, 정렬, ...했지만. 스트림이 중복제거->자르고->정렬 이렇게 하는게 아니에요. 바로 하지 않고, 이 스트림을 가지고 어떤 작업을 해야하는지 표시만 해놨다가 나중에 필요할 때 수행해요.

2-4. 반복을 내부 반복으로 처리한다

for(String str : strList)
	System.out.prinlt(str);
↓  
stream.forEach(System.out::println);

2-5. 스트림의 작업을 병렬로 처리 - 병렬스트림

  • 병렬 스트림
Stream<String> strStream = Stream.of("dd","aaa","CC","cc","b");
int sum = str.stream.parallel() 	//병렬 스트림으로 전환
					.mapToInt(s->s.length()).sum();

  • 기본형 스트림 : IntStream, LongStream, DoubleStream
    - 오토박싱&언박싱의 비효율이 제거됨 (Stream 대신 intStream사용)
    - 숫자와 관련된 유용한 메서드를 Stream보다 더 많이 제공(이건 가볍게 알아만 두세요)
    기본형 스트림은 몰라도 되는데 성능을 개선하고 싶을 때 사용합니다. 공부할 때 부담갖지 마시기 바라요.

3. 스트림 만들기

3-1. 컬렉션

  • Collection 인터페이스의 stream()으로 컬렉션을 스트림으로 변환
    Stream<E> stream() //Collection 인퍼에시으스이 메서드
List<Integer list = Arrats.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream();	//list를 스트림으로 변환
//스트림의 모든 요소를 출력
intStream.forEach(System.out::print);		//메서드 참조형
intStream.forEach((i)->System.out.println(i)); 		

3. 스트림 만들기

3-1. 스트림 만들기 - 배열

  • 객체 배열로부터 스트림 생성하기
Stream<T> Stream.of(T...vlues) 		//가변인자
Stream<T> Stream.of(T[])
Stream<T> Arrays.strea(T[])
Stream<T> Arrays.stream(T[] array, int startInclusice, int endExclusive)
Stream<String> strStream = Stream.of("a","b","c);	//가변인자
Stream<String> strStream = Stream.of(new String[]{"a","b","c"});
Stream<String> strStream = Arrays.stream(new String[]{"a","b","c"});
Stream<String> strStream = Arrays.stream(new String[] {"a","b","c"},0,3);
  • 기본형 배열로부터 스트림 생성하기
IntStream.IntStream.of(int...values)        //Stream 아니라 IntStream
IntStream.IntStream.of(int[])
IntStream.Arrays.stream(int[])
IntStream.Arrays.stream(int[] array, int startIncluesive, int endExclusive)

실습

//방법1
Stream<String> strStream = Stream.of("a","b","c");
		
//방법2
String[] strArr2 = new String[] {"a","b","c","d"};
Stream<String> strStream2 = Stream.of(strArr2);
		
//방법3
String[] strArr3 = {"a","b","c","d"};
Stream<String> strStream3 = Arrays.stream(strArr3);
		
//방법1
int[] intArr = {1,2,3,4,5};
IntStream intStream = Arrays.stream(intArr);
//count()말고도 다른 메서드들이 많이 있음
System.out.println(intStream.sum());
System.out.println(intStream.average());
		
//방법2
Integer[] intArr2 = {1,2,3,4,5};
//int[] intArr2 = {1,2,3,4,5}; 안됨. int배열이라 <Integer>스트림으로 못 받음
Stream<Integer> intStream2 = Arrays.stream(intArr2);
//count()만 있음
System.out.println(intStream2.count());	

3-2. 스트림 만들기 - 임의의 수(난수)

  • 난수를 요소로 갖는 스트림 생성하기
IntStream intStream1 = new Random().ints();
intStream.limit(5).forEach(System.out::println);	//limit로 잘라서 5개 요소만 출력한다
		
IntStream intStream3 = new Random().ints(5);		//크기가 5인 난수 스트림을 반환


3-3. 특정 범위의 정수를 요소로 갖는 스트림 생성하기(IntStream, LongStream)

간단한 거니까 실습을 생략할게요

3-4. 스트림 만들기 - 람다식 iterate(), generate()

  • 무한 스트림
  • 람다식을소스로 하는 스트림 생성하기

3-5. 스트림 만들기 - 파일과 빈 스트림

  • 파일을 소스로 하는 스트림 생성하기
    Stream<Path> Files.list(Path dir) : Path는 파일 또는 디렉토리
Stream<String> Files.line(Path path)
Stream<String> Files.ines(Path path, Charset cs)
Stream<String> lines()		//BuggeredReader 클래스의 메서드
  • 비어있는 스트림 생성하기(있다는 정도로만 알아두세요. 자주 쓰이지는 않음)
Stream emptySream = Stream.empty();
long count = emptyStream.count();		//카운트의 값은 0

4. 중간 연산

  • 연산 결과가 스트림
  • 중간 연산의 핵심은 map과 flatMap 이게 좀 어려워요

4-1. 스트림 자르기

  • skip(), limit()

4-2. 스트림의 요소 걸러내기

  • filter(), distinct()

4-3. 스트림 정렬하기

  • sort()

4-4. Comparator의 comparing()으로 정렬 기준을 제공

public class Ex14_5 {

	public static void main(String[] args) {
		Stream<Student> studentStream = Stream.of(
				new Student("이자바",3,300),
				new Student("김자바",3,300),
				new Student("안자바",3,300),
				new Student("박자바",3,300),
				new Student("소자바",3,300),
				new Student("나자바",3,300),
				new Student("감자바",3,300)
				);
		studentStream.sorted(Comparator.comparing(Student::getBan)
				.thenComparing(Comparator.naturalOrder()))
				.forEach(System.out::println);
	}
}

class Student implements Comparable<Student> {

	String name;
	int ban;
	int totalScore;
	
	Student(String name, int ban, int totalScore) {
		this.name = name;
		this.ban = ban;
		this.totalScore = totalScore;
	}
	
	public String toString() {
		return String.format("[%s, %d, %d]", name, ban, totalScore);
	}
	
	String getName() {return name;}
	int getBan() {return ban;}
	int getTotalScore() {return totalScore;}
	
	
	public int compareTo(Student s) {
		return s.totalScore - this.totalScore;
	}	
}

4-4. 스트림의 요소 변환하기

  • map()

public class Ex14_5 {

	public static void main(String[] args) {
		File[] fileArr = {new File("Ex1.java"), new File("ex1,bak"),
				new File("Ex2.java"), new File("Ex1"), new File("Ex1.txt")};
	
	
	Stream<File> fileStream = Stream.of(fileArr);
	Stream<String> filenameStream = fileStream.map(File::getName);
	filenameStream.forEach(System.out::println);
	
	fileStream = Stream.of(fileArr); 		//스트림을 다시 생성
	
	fileStream.map(File::getName)
				.filter(s->s.indexOf('.')!=-1)			//확장자가 없는 것은 제외
				.forEach(System.out::println);			
	}	
}  

4-5. 스트림의 요소를 소비하지 않고 엿보기

  • peek()
    중간확인용으로 씀.

4-6. 스트림의 스트림을 스트림으로 변환

  • flatMap()


    ↑여기서 두번째꺼. 두 문장을 하나하나 단어로 스트림 만들때도 flatmap을 써야 함

4-6. Optional

  • T타입 객체의 래퍼클래스
    왜 필요?
  1. null을 직접 다루는 것은 위험(널 포인터 익셉션)
  2. null체크(if문 필수 ->코드가 지저분) 안 해도 됨
    이거는 null을 Optional에 객체로 넣는거. null값인 객체.
    그러면 결과가 null이더라도 result의 값은 항상 null이 아님.
public final class Iotional<T> {
  private final T value;	//T타입의 참조변수
  		...
  }

Optional 객체를 생성하는 다양한 방법

Streing str - "Abc";
Optional<String> optVal = Optional.of(str);
Optional<String> optVal = OPtional.of("abc");
Optional<String> optVal = OPtional.if(null);		//널포인터익셉션 발생
Optional<String> optVal = OPtional.ofNullable(null)	//OK

널을 넣는건 안되므로, 널을 저장할 수 있는 Opational은 네번째꺼. 그럼 널을 넣고 싶으면 보통 네 번째꺼를 쓰겠죠.

↑ 한단계 더 거치는 것

  • null 대신 빈 Optional객체를 사용하자
    Optiona optVal = null; //널로 초기화. 바람직하지 않음.
    Optiona optVal = Optional.empty(); //빈 겍체로 초기화.
    뒤에 은 생략가능
    ✏✏우리 Myvector에서 배웠잖아요.
Object[] objArr = null; 로 하지 말고
objArr = new Object[0];		//크기 0인걸로 초기화하자고.

이렇게 하는 것들이 null포인터 익셉션을 피하기 위한거에요.

4-6. Optional 객체의 값 가져오기

  • get(), ofLese(), orElseGet(), orElseThrow()
  • orElseGet(), orElseThrow()를 많이 써요. 나머지는 null일때 에러나서 잘 안 써요


    (String::new) 는 ()->new String()
  • isPresent()
    Optional객체의 값이 null이면 false, 아니면 true를 반환

4-7. OptionalInt, OptionalLong, OPtionalDouble

  • 기본형 값을 감싸는 래퍼클래스
    Optional를 써도 되는데, 더 높은 성능이 필요할 때 쓰는 것들.
public final class OptionalInt{
  private final boolean isPresent;
  private final int value;
  }
  • Optional 값 가져오기 - int getAsInt()
  • 빈 Optional 객체와의 비교
OptionalInt opt = OptionalInt.of(0);  	//OptionalInt에 0 저장
OptionalInt opt2 = OptionalInt.empty();	//OptionalInt에 0 저장

이것을 어떻게 구별? 구별 가능?
그러니까 ispresent를 쓰는 것.

System.out.println(opt.ispresent());		//true
System.out.println(opt2.ispresent());		//false
System.out.println(opt.equals(opt2));		//false

4. 최종 연산


findAny() : 병렬 - filter랑 같이 쓰임
indFirst() : 직렬 - filter랑 같이 쓰임...?
reduce(), collect()가 최종연산의 핵심

4-1. forEach(), forEachOrdered()

  • 스트림의 모든 요소에 지정된 작업을 수행

4-2. allMatch(), anyMatch(), noneMatch()

  • 조건검사

4-3. findFirst(), findAny()

4-4. reduce()

  • 스트림의 요소를 하나씩 줄여가며 누적연산 수행

4-5. collect()와 Collectors

  • collect()는 Collector를 매개변수로 하는 스트림의 최종 연산
  • reduce()와 차이점: 그룹별 리듀싱이 가능

4-6. 스트림을 컬렉션, 배열로 변환

0개의 댓글