자바 스트림(Stream)은 데이터를 다루고 처리하는데 사용되는 시퀀스(순서)로, 컬렉션, 배열 등의 데이터 소스로부터 데이터를 읽거나 처리하는 기능을 제공하는 자바 8의 기능이다.
스트림은 함수형 프로그래밍 스타일을 지원하며, 데이터를 처리하는 과정을 간결하게 나타내고 병렬 처리를 지원한다.
Collections 인터페이스의 stream() 메서드로 스트림 생성
ArrayList<Integer> list = new ArrayList<>();
list.add(4);
list.add(3);
list.add(2);
list.add(1);
// 컬렌션으로부터 스트림 생성
Stream<Integer> stream = list.stream();
// forEach() 메서드로 스트림 요소에 순차 접근
stream.forEach(System.out::println);
Arrays 클래스의 stream() 메서드 사용
String[] arr = {"넷", "셋", "둘", "하나"};
// 배열로 스트림 생성
Stream<String> stream = Arrays.stream(arr);
// 배열의 특정 부분으로 스트림 생성
Stream<String> stream2 = Arrays.stream(arr, 1, 3);
Stream의 of() 메서드를 사용하여 가변 매개변수로 stream 생성
Stream<Double> stream = Stream.of(1.2, 4.3, 2.3);
IntStream의 range()와 rangeClosed() 메서드 사용
range()
: 마지막 정수는 포함하지 않는다.
rangeClosed()
: 마지막 정수까지 포함한다.
IntStream stream1 = range(1, 4); // 1 2 3
IntStream stream2 = rangeClosed(1, 4);// 1 2 3 4
empty() 메서드 사용
Stream<Object> stream = Stream.empty();
System.out.println(stream.count()); // 0 출력
스트림을 전달받아 스트림을 바환하므로, 연속으로 연결해서 사용할 수 있다.
filter()
: 주어진 조건에 맞는 요소만으로 구성된 스트림 반환
distinct()
: 중복된 요소가 제거된 스트림 반환
IntStream stream1 = IntStream.of(1,1,2,3,3,3);
IntStream stream2 = IntStream.of(1,1,2,3,3,3);
stream1.filter(i -> i % 2 != 0).forEach(i -> System.out.print(i + " ");
// 1 3
stream2.distinct().forEach(i -> System.out.print(i + " "));
// 1 2 3
map()
: 해당 스트림의 요소들을 주어진 함수에 인수로 전달하여 반환값들로 이루어진 스트림을 반환한다.
예제
Stream<String> stream = Stream.of("1","22", "333", "4444");
stream.map(s -> s.length()).forEach(System.out:println);
실행 결과
1
2
3
4
limit()
: 첫 번째 요소부터 전달된 개수만큼의 요소만으로 이루어진 스트림 반환
skip()
: 첫 번째 요소부터 전달된 개수만큼의 요소를 제외한 나머지 요소만으로 이루어진 스트림 반환
IntStream stream1 = IntStream.range(0,10);
IntStream stream2 = IntStream.range(0,10);
IntStream stream3 = IntStream.range(0,10);
stream.limit1(5).forEach(i -> System.out.println(i + " ");
// 0 1 2 3 4
steam2.skip(5).forEach(i -> System.out.println(i + " ");
// 5 6 7 8 9
stream3.skip(3).limit(5).forEach(i -> System.out.println(i + " ");
// 3 4 5 6 7
sorted()
: 주어진 비교자를 이용하여 정렬
비교자를 전달하지 안흥면 사전 순으로 오름차순
Stream<String> stream1 = Stream.of("JAVA", "CSS", "HTML");
Stream<String> stream2 = Stream.of("JAVA", "CSS", "HTML");
stream1.sorted().forEach(s -> System.out.println(s + " ");
// CSS HTML JAVA
stream.sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s + " ");
// JAVA HTML CSS
중개 연산을 통해 변환된 스트림은 마지막으로 최종 연산을 통해 각 요소를 소모하여 결과를 표시한다.
최종 연산에 사용된 스트림은 더 사용할 수 없다.
stream.forEach(System.out::println);
findFirst()
와 findAny()
메소드는 해당 스트림에서 첫 번째 요소를 참조하는 Optional 객체를 반환한다.
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 반환
* 모든 요소를 검사하여 3보다 큰 요사가 하나라도 존재하면 true
IntStream stream = IntStream.of(1,2,3,4);
stream.anyMatch(n -> n > 3);
// true
allMatch()
: 모든 요소가 특정 조건을 만족해야 true 반환
IntStream stream = IntStream.rangeClosed(1,4);
stream.allMatch(n -> n > 3);
// false
count()
: 요소의 총 개수를 long 타입으로 반환
max(), min()
: 요소 중 가장 큰 값과 가장 작은 값을 Optional 객체로 반환
IntStream stream1 = IntStream.rangeClosed(1,10);
IntStream stream2 = IntStream.rangeClosed(1,10);
stream1.count() // 10
stream2.max().getAsInt() // 10
sum()
, average()
IntStream stream1 = IntStream.of(1, 2, 3, 4);
System.out.println(stream1.sum()); // 10
DoubleStream stream2 = DoubleStream.of(30.3, 90.9, 70.7, 10.1);
System.out.println(stream2.average().getAsDouble()); // 50.5
collect()
메소드로 스트림을 리스트로 변환
Stream<String> stream = Stream.of("넷", "둘", "하나", "셋");
List<String> list = stream.collect(Collectors.toList());