1) 외부 반복을 통해 작업하는 컬렉션과는 달리 내부 반복을 통해 작업 수행.
2) 재사용이 가능한 컬렉션과를 달리 단 한번만 사용할 수 있음.
3) 원본 데이터를 변경하지 않음.
4) 필터-맵 기반의 API를 사용하여 지연연산을 통해 성능을 최적화함.
5) parallelStream()
메서드를 통한 손쉬운 병렬처리 지원.
stream()
메서드가 정의되어 있음 .forEach()
메서드는 해당 메서드의 요소를 하나씩 순차적으로 접근하며 같은 스트림에서 한번만 호출 가능.ArrayList<Integer> list = new ArrayList<Integer>();
list.add(4);
list.add(2);
list.add(3);
list.add(1);
// 컬렉션에서 스트림 생성
Stream<Integer> stream = list.stream();
// forEach() 메소드를 이용한 스트림 요소의 순차 접근
stream.forEach(System.out::println); // :: 클래스에서 직접 메서드를 참조시켜 사용할때 사용 (주로 List)
stream(배열)
, stream(배열, 시작인덱스[포함O], 종료인덱스[포함X])
String[] arr = new String[]{"넷", "둘", "셋", "하나"};
// 배열에서 스트림 생성
Stream<String> stream1 = Arrays.stream(arr);
stream1.forEach(e -> System.out.print(e + " ")); // 넷 둘 셋 하나
System.out.println();
// 배열의 특정 부분만을 이용한 스트림 생성
Stream<String> stream2 = Arrays.stream(arr, 1, 3);
stream2.forEach(e -> System.out.print(e + " ")); //둘 셋
of()
메서드를 사용하여 매개변수를 전달받아 생성할 수 있음.Stream.of(매개변수1, 매개변수 2, 매개변수3....);
// 가변 매개변수에서 스트림 생성
Stream<Double> stream = Stream.of(4.2, 2.5, 3.1, 1.9);
stream.forEach(System.out::println);
range(시작숫자, 종료숫자)
와 rangeClosed(시작숫자, 종료숫자)
메서드를 이용하여 지정된 범위의 연속된 정수를 스트림으로 생성할 수 있음.// 지정된 범위의 연속된 정수에서 스트림 생성
IntStream stream1 = IntStream.range(1, 4);
stream1.forEach(e -> System.out.print(e + " ")); //1 2 3
IntStream stream2 = IntStream.rangeClosed(1, 4);
stream2.forEach(e -> System.out.print(e + " ")); //1 2 3 4
ints()
, longs()
, doubles()
와 같은 메서드로 스트림을 생성할 수 있음.limit()
메서드를 사용하여 따로 스트림의 크기를 제한해주어야함.// 특정 타입의 난수로 이루어진 스트림 생성
IntStream stream = new Random().ints(4);
stream.forEach(System.out::println); //난수 4개
iterate()
와 generate()
메서드를 사용하여 람다표현식을 매개변수로 전달받아 람다식 반환값을 요소로 하는 무한 스트림 생성 가능.Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6, ...
==> generate()는 매개변수가 없는 람다식을 사용하여 반환된 값으로 무한 스트림 생성.
Stream<Double> randomStream = Stream.generate(Math::random);
Stream<Integer> oneStream = Stream.generate(()->1); // 1, 1, 1, 1 ...
lines()
메서드로 파일의 한 행을 요소로 하는 스트림 생성가능.lines()
메서드를 사용하면 파일뿐만 아니라 다른 입력의 데이터도 행단위로 읽어올 수 있음.String<String> stream = Files.lines(Path path);
empty()
메서드를 이용하여 아무요소도 가지지 않는 빈 스트림을 생성할 수 있음.// 빈 스트림 생성
Stream<Object> stream = Stream.empty();
System.out.println(stream.count()); // 스트림의 요소의 총 개수를 출력함. : 0
필터-맵(filter-map)
기반의 API를 사용함으로 지연(lazy)연산을 통해 성능을 최적화 할 수 있음.filter()
, distinct()
map()
, flatMap()
limit()
, skip()
sorted()
peek()
filter()
메서드는 해당 스트림에서 주어진 조건(predicate)에 맞는 요소로만 이루어진 새로운 스트림 반환함.distinct()
메서드는 해당 스트림에서 중복된 요소가 제거된 새로운 스트림을 반환.equals()
메서드를 사용하여 요소의 중복을 비교함.IntStream stream1 = IntStream.of(7, 5, 5, 2, 1, 2, 3, 5, 4, 6);
IntStream stream2 = IntStream.of(7, 5, 5, 2, 1, 2, 3, 5, 4, 6);
// 스트림에서 중복된 요소를 제거함.
stream1.distinct().forEach(e -> System.out.print(e + " ")); //7 5 2 1 3 4 6
// 스트림에서 홀수만을 골라냄.
stream2.filter(n -> n % 2 != 0).forEach(e -> System.out.print(e + " ")); //7 5 5 1 3 5
map()
메서드는 해당 스트림의 요소들을 주어진 함수에 인수로 전달하고, 그 반환값들로 이루어진 새로운 스트림을 반환함.flatMap()
메서드를 사용하여 배열의 각 요소의 반환값을 하나로 합친 새로운 스트림 반환.//문자열로 이루어진 스트림을 문자열의 길이로 이루어진 스트림으로 변환
Stream<String> stream = Stream.of("HTML", "CSS", "JAVA", "JAVASCRIPT");
stream.map(s -> s.length()).forEach(System.out::println); //4 3 4 10
//여러문자열이 저장된 배열을 문자열에 포함된 단어로 이루어진 스트림으로 변환
String[] arr = {"I study hard", "You study JAVA", "I am hungry"};
Stream<String> stream = Arrays.stream(arr);
stream.flatMap(s -> Stream.of(s.split(" "))).forEach(System.out::println); //공백을 기준으로 잘라서 스트림에 저장.
limit()
메서드는 해당 스트림의 첫번째 요소부터 전달된 개수만큼의 요소로 이루어진 새 스트림을 반환함.skip()
메서드는 해당 스트림의 첫번째 요소부터 전달된 개수만큼의 요소를 제외한 나머지 요소로 이루어진 새 스트림을 반환함.IntStream stream1 = IntStream.range(0, 10); //0~9
IntStream stream2 = IntStream.range(0, 10);
IntStream stream3 = IntStream.range(0, 10);
stream1.skip(4).forEach(n -> System.out.print(n + " ")); // 4 5 6 7 8 9
stream2.limit(5).forEach(n -> System.out.print(n + " ")); // 0 1 2 3 4
stream3.skip(3).limit(5).forEach(n -> System.out.print(n + " ")); // 3 4 5 6 7
store()
메서드는 해당 스트림을 주어진 비교자(comparator)를 이용하여 정렬함.Stream<String> stream1 = Stream.of("JAVA", "HTML", "JAVASCRIPT", "CSS");
Stream<String> stream2 = Stream.of("JAVA", "HTML", "JAVASCRIPT", "CSS");
stream1.sorted().forEach(s -> System.out.print(s + " ")); //CSS HTML JAVA JAVASCRIPT
stream2.sorted(Comparator.reverseOrder()).forEach(s -> System.out.print(s + " ")); //JAVASCRIPT JAVA HTML CSS
peek()
메서드는 결과 스트림으로 부터 요소를 소모하여 추가로 명시된 동작을 수행함.IntStream stream = IntStream.of(7, 5, 5, 2, 1, 2, 3, 5, 4, 6);
stream.peek(s -> System.out.println("원본 스트림 : " + s))
.skip(2)
.peek(s -> System.out.println("skip(2) 실행 후 : " + s))
.limit(5)
.peek(s -> System.out.println("limit(5) 실행 후 : " + s))
.sorted()
.peek(s -> System.out.println("sorted() 실행 후 : " + s))
.forEach(n -> System.out.println(n));
<결과>
원본 스트림 : 7
원본 스트림 : 5
원본 스트림 : 5
skip(2) 실행 후 : 5
limit(5) 실행 후 : 5
원본 스트림 : 2
skip(2) 실행 후 : 2
limit(5) 실행 후 : 2
원본 스트림 : 1
skip(2) 실행 후 : 1
limit(5) 실행 후 : 1
원본 스트림 : 2
skip(2) 실행 후 : 2
limit(5) 실행 후 : 2
원본 스트림 : 3
skip(2) 실행 후 : 3
limit(5) 실행 후 : 3
sorted() 실행 후 : 1
1
sorted() 실행 후 : 2
2
sorted() 실행 후 : 2
2
sorted() 실행 후 : 3
3
sorted() 실행 후 : 5
5
forEach()
reduce()
findFirst()
, findAny()
anyMatch()
, allMatch()
, noneMatch()
count()
, min()
, max()
sum()
, average()
collect()
forEach()
메서드는 스트림의 각 요소를 소모하여 명시된 동작을 수행함.reduce()
메서드는 첫번째와 두번째 요소를 가지고 연산 수행 후 그 결과를 다음 요소와 다시 연산을 수행하는 방식으로 모든 요소를 소모하고 그 결과를 반환함.// 각 문자열 요소를 "++"기호로 연결하여 출력하는 예제
Stream<String> stream1 = Stream.of("넷", "둘", "셋", "하나");
Stream<String> stream2 = Stream.of("넷", "둘", "셋", "하나");
Optional<String> result1 = stream1.reduce((s1, s2) -> s1 + "++" + s2);
result1.ifPresent(System.out::println); // 넷++둘++셋++하나
String result2 = stream2.reduce("시작", (s1, s2) -> s1 + "++" + s2);
System.out.println(result2); // 시작++넷++둘++셋++하나
==> 초깃값을 전달하면 Optional<T>가 아닌 T타입으로 반환 (빈 스트림과 연산할 경우 전달받은 초깃값을 그대로 반환해야하기 때문)
findFirst()
와 findAny()
메서드는 해당 스트림에서 첫번째 요소를 참조하는 Optional객체를 반환함.==> filter()를 사용할 경우 조건에 맞는 첫번째 요소를 반환 하는데 findFirst()는 가장 앞의 요소를 반환하고 findAny()는 가장 먼저 발견한 요소를 반환.
==> 두 메서드 모두 빈 스트림에서는 비어있는 Optional객체를 반환.
==> 병렬 스트림의 경우 findAny()를 사용해야 정확한 결과를 반환받을 수 있음.
// 스트림 정렬 후 첫 요소를 출력
IntStream stream1 = IntStream.of(4, 2, 7, 3, 5, 1, 6);
IntStream stream2 = IntStream.of(4, 2, 7, 3, 5, 1, 6);
OptionalInt result1 = stream1.sorted().findFirst();
System.out.println(result1.getAsInt()); //1
OptionalInt result2 = stream2.sorted().findAny();
System.out.println(result2.getAsInt()); //1
anyMatch()
메서드는 해당 스트림의 일부 요소가 특정 조건을 만족할 때 true를 반환. // ORallMatch()
메서드는 해당 스트림의 모든 요소가 특정 조건을 만족할 때 true를 반환. // ANDnoneMatch()
메서드는 해당 스트림의 모든 요소가 특정 조건을 만족하지 않을 때 true를 반환. // NOT// 80보다 큰값을 가지는 요소가 있는지 검사
IntStream stream1 = IntStream.of(30, 90, 70, 10);
IntStream stream2 = IntStream.of(30, 90, 70, 10);
System.out.println(stream1.anyMatch(n -> n > 80)); // true
System.out.println(stream2.allMatch(n -> n > 80)); // false
count()
메서드는 해당 스트림의 요소의 총 개수를 long타입으로 반환.max()
와 min()
메서드는 해당스트림의 요소중 가장 큰 값 또는 가장 작은 값을 가지는 요소를 참조하는 Optional객체를 반환.IntStream stream1 = IntStream.of(30, 90, 70, 10);
IntStream stream2 = IntStream.of(30, 90, 70, 10);
System.out.println(stream1.count()); // 4
System.out.println(stream2.max().getAsInt()); // 90
sum()
과 average()
메서드가 기본 제공됨.IntStream stream1 = IntStream.of(30, 90, 70, 10);
DoubleStream stream2 = DoubleStream.of(30.3, 90.9, 70.7, 10.1);
System.out.println(stream1.sum()); // 200
System.out.println(stream2.average().getAsDouble()); // 50.5
collect()
메서드는 인수로 전달되는 Collectors객체에 구현된 방법대로 스트림의 요소를 수집함.① 스트림을 배열이나 컬렉션으로 변환 : toArray()
, toCollection()
, toList()
, toSet()
, toMap()
Stream<String> stream = Stream.of("넷", "둘", "하나", "셋");
List<String> list = stream.collect(Collectors.toList()); //List로 변환
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
System.out.print(iter.next() + " "); // 넷 둘 하나 셋
}
② 요소의 통계와 연산 메소드와 같은 동작을 수행 : counting()
, maxBy()
, minBy()
, summingInt()
, averagingInt()
등
③ 요소의 소모와 같은 동작을 수행 : reducing()
, joining()
④ 요소의 그룹화와 분할 : groupingBy()
, partitioningBy()
// 해당 스트림의 각 요소의 글자수에 따라 홀수와 짝수로 나누어 저장
Stream<String> stream = Stream.of("HTML", "CSS", "JAVA", "PHP");
Map<Boolean, List<String>> patition = stream.collect(Collectors.partitioningBy(s -> (s.length() % 2) == 0)); // 글자가 짝수면 true 홀수면 false로 나누어서 map으로 저장
// 홀수인것들만 저장한 List
List<String> oddLengthList = patition.get(false);
System.out.println(oddLengthList); // [CSS,PHP]
// 짝수인것들만 저장한 List
List<String> evenLengthList = patition.get(true);
System.out.println(evenLengthList); // [HTML, JAVA]