[Java] 스트림(Stream)

이다혜·2023년 11월 7일
0

Java

목록 보기
17/23
post-thumbnail

스트림이란?

자바 스트림(Stream)은 데이터를 다루고 처리하는데 사용되는 시퀀스(순서)로, 컬렉션, 배열 등의 데이터 소스로부터 데이터를 읽거나 처리하는 기능을 제공하는 자바 8의 기능이다.

스트림은 함수형 프로그래밍 스타일을 지원하며, 데이터를 처리하는 과정을 간결하게 나타내고 병렬 처리를 지원한다.

특징

  1. 외부 반복을 통해 작업하는 컬렉션과 달리 내부 반복을 통해 작업을 수행한다.
  2. 재사용이 가능한 컬렉션과 달리 단 한번만 사용할 수 있다.
  3. 원본 데이터를 벼경하지 않는다.
  4. 필터 - 맵 기반의 API를 사용하여 성능을 최적화한다.
  5. 손쉬운 병렬 처리를 지원한다.

동작 흐름

  1. 스트림 생성
  2. 중개 연산(스트림의 변환)
  3. 최종 연산(스트림의 사용)

1. 스트림 생성

1) 컬렉션

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);

2) 배열

Arrays 클래스의 stream() 메서드 사용

String[] arr = {"넷", "셋", "둘", "하나"};

// 배열로 스트림 생성
Stream<String> stream = Arrays.stream(arr);

// 배열의 특정 부분으로 스트림 생성
Stream<String> stream2 = Arrays.stream(arr, 1, 3);

3) 가변 매개변수

Stream의 of() 메서드를 사용하여 가변 매개변수로 stream 생성

Stream<Double> stream = Stream.of(1.2, 4.3, 2.3);

4) 지정된 범위의 연속된 정수

IntStream의 range()와 rangeClosed() 메서드 사용
range() : 마지막 정수는 포함하지 않는다.
rangeClosed() : 마지막 정수까지 포함한다.

IntStream stream1 = range(1, 4); // 1 2 3
IntStream stream2 = rangeClosed(1, 4);// 1 2 3 4

5) 빈 스트림

empty() 메서드 사용

Stream<Object> stream = Stream.empty();
System.out.println(stream.count()); // 0 출력

2. 스트림의 중개 연산

스트림을 전달받아 스트림을 바환하므로, 연속으로 연결해서 사용할 수 있다.

대표적인 중개연산

  1. 필터링 : filter(), distinct()
  2. 변환 : map(), flatMap()
  3. 제한 : limit(), skip()
  4. 정렬 : sorted()

1) 스트림 필터링

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 

2) 스트림 변환

map() : 해당 스트림의 요소들을 주어진 함수에 인수로 전달하여 반환값들로 이루어진 스트림을 반환한다.


예제

Stream<String> stream = Stream.of("1","22", "333", "4444");
stream.map(s -> s.length()).forEach(System.out:println);

실행 결과

1
2
3
4

3) 스트림 제한

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 

4) 스트림 정렬

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

3. 스트림의 최종 연산

중개 연산을 통해 변환된 스트림은 마지막으로 최종 연산을 통해 각 요소를 소모하여 결과를 표시한다.

최종 연산에 사용된 스트림은 더 사용할 수 없다.

대표적인 최종연산

  1. 출력 : forEach()
  2. 검색 : findFirst(), findAny()
  3. 요소의 검사 : anyMatch(), allMatch(), noneMatch()
  4. 요소의 통계 : count(), min(), max()
  5. 요소의 연산 : sum(), average()
  6. 요소의 수집 : collect()

1) 출력

stream.forEach(System.out::println);

2) 검색

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

3) 검사

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

4) 통계

count() : 요소의 총 개수를 long 타입으로 반환
max(), min() : 요소 중 가장 큰 값과 가장 작은 값을 Optional 객체로 반환

IntStream stream1 = IntStream.rangeClosed(1,10);
IntStream stream2 = IntStream.rangeClosed(1,10);

stream1.count() // 10
stream2.max().getAsInt() // 10

5) 연산

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

6) 수집

collect() 메소드로 스트림을 리스트로 변환

Stream<String> stream = Stream.of("넷", "둘", "하나", "셋");

List<String> list = stream.collect(Collectors.toList());

0개의 댓글