Stream의 객체를 구성하고자 할 때 "Stream 생성 → 중간 연산→ 최종 연산"의 세 단계의 과정을 통해서 Stream의 구성이 이루어집니다.
이번 포스팅에서는 Stream 생성 후 생성된 스트림을 필터링하거나 원하는 형태에 알맞게 가공하는 연산을 하는 과정인
Stream 중간 연산에 대해 알아보겠습니다.
Stream 중간 연산(가공)이란❓
Stream 중간 연산은 Stream 생성으로 만들어진 데이터 집합을 원하는 형태로 가공하는 것으로 중간 처리를 의미합니다.
중간 연산의 입력값과 반환 값은 "Stream"입니다. 따라서 여러번 사용할 수 있는 메서드 체이닝이 가능합니다.
지연 평가(Lasy Evaluation)
중간 연산은 Stream을 다른 Stream으로 변환하거나 필터링하는 "중간" 작업을 수행하기 때문에 연산을 호출할 때 즉시 수행되지 않고 최종 메소드가 실행되기 전까지 연산을 실행하지 않는 "지연 평가"로 실행됩니다.
Stream 중간 연산의 메서드
분류 | 상세 분류 | 설명 |
Stream 필터링 | filter(), distinct(), limit() | • filter()는 구성한 스트림 내에서 특정 조건에 맞는 결과값을 필터링 하기 위해 사용됩니다. • distinct()는 구성한 스트림 내에서 중복을 제거한 결과값을 반환하기 위해 사용됩니다. |
Stream 변환 | map(), flatMap(), mapToInt(), mapToLong(), mapToDouble() | • map()은 구성한 스트림 내에서 요소들을 원하는 값으로 변환하여서 반환하기 위해 사용됩니다. • flatMap()는 구성한 스트림 내에서 중복된 스트림을 평면화(flattern)하여 요소를 구성하여 반환하기 위해 사용됩니다. |
Stream 제한 | limit(), skip() | - limit()는 구성한 스트림 내에서 요소의 개수를 제한하여 반환해주기 위한 목적으로 사용됩니다. - skip()는 구성한 스트림 내에서 시작부터 특정 n개의 요소를 제외하여 반환해주는 목적으로 사용합니다. |
Stream 정렬 | sorted() | - sorted()는 구성한 스트림 내에서 배열 혹은 리스트 그리고 Object의 요소에 대해서 오름/내림 차순을 수행하여 반환해주는 함수입니다. |
Stream 연산 결과 확인 | peek() | - peek()는 구성한 스트림 내에서 각각의 요소를 조회하는 연산자료 요소 자체를 추출하는것이 아닌 스트림의 요소를 조회하는 함수입니다. |
Stream 필터링
Filtering
Stream<T> filter(Predicate<? super T> condition);
Stream 클래스에서 제공하는 filter() 메서드는 인자로 받는 predicate는 boolean을 리턴하는 함수형 인터페이스이며, 조건식을 표현하는 데 사용됩니다.
Array
int[] filterIntArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 배열
IntStream filterIntStream = Arrays.stream(filterIntArr).filter(item -> item % 2 == 0);
filterIntStream.forEach(System.out::print); // 결과 : 2,4,6,8,10
ArrayList
List<String> filterStrList = new ArrayList<>(Arrays.asList("kim", "park", "park", "lee", "Son"));
// 2. ArrayList to Stream<String> : 리스트 내에 "park"가 존재하는 배열을 찾습니다.
Stream<String> filterStrStream = filterStrList.stream().filter(item -> item.equals("park"));
// 3. Stream<String> to ArrayList
filterStrList = filterStrStream.collect(Collectors.toList()); // 결과값 반환 : ["lee", "lee"]
Stream이 아닌 List로 반환받고 싶다면 중간 연산 filter() 뒤에 Collectors 클래스의 toList() 메서드를 매개변수로 가지는 collect() 메서드를 호출하면 됩니다.
필터링 기준이 여러 개인 경우
public static void main(String args[]) {
String[] arr = {"ABC", "EDF", "EDZ", "CS", "AB"};
List<String> strList = new ArrayList<>(Arrays.asList(arr));
Stream<String> filterResult =
arr.stream().filter((item) -> {
return item.startsWith("A") && item.endsWith("B") && item.length() < 3;
});
filterResult.forEach(System.out::println); // 결과 : AB
}
• filter : Stream 내 요소들을 하나씩 비교하여 요소들을 조건에 맞게 필터링하기 위한 메서드입니다.
distinct
Stream<T> distinct();
distinct는 중복제거 메서드로, Stream에서 중복된 요소를 제거한 Stream을 반환합니다.
Array
List<String> list = Arrays.asList("A", "A", "B", "B", "C", "C");
Stream<String> stream = list.stream().distinct();
System.out.println(stream.collect(Collectors.toList())); // [A, B, C]
ArrayList
List<String> distinctStrList = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "A"));
Stream<String> distinctStrStream = distinctStrList.stream().distinct();
distinctStrList = distinctStrStream.collect(Collectors.toList());
System.out.println(distinctStrList); // 결과 : ["A", "B", "C", "D"]
Stream 변환(Mapping)
Stream의 각 요소마다 수행할 연산을 구현하는 데 사용됩니다.
map
List<String> list = Arrays.asList("A", "B", "C", "D");
Stream<String> stream = list.stream()
.map(s -> s.toLowerCase())
.forEach(n->System.out.println(n)); // [a,b,c,d]
map 메서드를 사용하여 스트림 내 요소를 특정 형태로 변환하는 데 사용됩니다.
인자로는 람다로 받으며, 기존 값을 변경하기보다 새로운 값을 값을 만든다는 개념입니다.
flatMap
flatMap은 Stream 내에서 중복된 스트림을 평면화(flattern)하여 요소를 구헝하여 반환하기 위해 사용됩니다.
중복된 구조의 리스트를 하나의 평면화된 리스트로 받습니다. 즉 하나의 스트림으로 합쳐서 반환해 주는 역할을 합니다.
ArrayList
int[][] int2Dimension = {{1, 2}, {3, 4}, {5, 6}};
int[] flatMapIntArr = Arrays.stream(int2Dimension).flatMapToInt(Arrays::stream).toArray();
// 결과값 반환: [1, 2, 3, 4, 5, 6]
ArrayList
List<String> list1 = List.of("mad", "play");
List<String> list2 = List.of("kim", "taeng");
List<List<String>> combinedList = List.of(list1, list2);
List<String> streamByList = combinedList.stream()
.flatMap(list -> list.stream())
.collect(Collectors.toList());
System.out.println(streamByList); // 결과 : mad, play, kim, taeng
mapToInt(), mapTolong(), mapToDouble()
IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
mapToInt(), mapToLong(), mapToDouble() 함수들은 Stream을 해당 타입으로 바꿔주는 역할을 합니다.
List<String> list = Arrays.asList("1", "2", "3", "4");
IntStream stream = list.stream()
.mapToInt(s -> Integer.parseInt(s)); // [1, 2, 3, 4] 정수형
Stream 제한
limit
List<String> list = List.of("a", "b", "c", "d").stream()
.limit(3).collect(Collectors.toList());
System.out.println(list); // 결과 : a,b,c
limit() 메서드를 사용하면 스트림 내 요소의 개수를 제한할 수 있습니다.
skip
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.filter(i -> i % 2 == 0)
.skip(2)
.forEach(i -> System.out.print(i + " ")); //결과: 6 8 10
Stream 메서드를 사용하면 처음 n개의 요소를 버리는 작업입니다.
Stream 정렬
Stream의 정렬도 다른 함수의 정렬과 마찬가지로 Comparator 인터페이스를 사용합니다.
List<Integer> list = Arrays.asList(5, 7, 3, 1, 2, 6, 1, 9, 0);
Stream<Integer> stream = list.stream()
.sorted(); // [0, 1, 1, 2, 3, 4, 5, 6, 7, 9]
인자 없이 출력하면 디폴트 값은 오름차순입니다. 오름차순이 아닌 다른 방식으로 정렬하고 싶을 땐 Comparator 또는 Comparable을 사용해서 정렬 형식을 지정해 주면 됩니다.
내림차순 출력
List<Integer> list = Arrays.asList(5, 7, 3, 1, 2, 6, 1, 9, 0);
Stream<Integer> stream = list.stream()
.sorted(Comparator.reverseOrder());
// [9, 7, 6, 5, 4, 3, 2, 1, 1, 0]
Collections.reverseOrder() 메서드를 이용하면 역순으로 정렬된 배열을 얻을 수 있습니다.
주의할 점은 정렬할 배열은 Primitive 타입이 아닌 Wrapper 클래스여야 합니다.
peak
int sum = intList.stream().filter(x -> x<=2)
.peek(System.out::println)
.mapToInt(Integer::intValue).sum();
System.out.println("sum: "+sum);
원본 Stream을 사용하는 것이 아니기 때문에 Stream 연산과정에서 중간 결과를 확인할 때 사용할 수 있습니다.
디버깅할 때 유용하게 사용할 수 있으며, 중간 연산에서 동작하지 않고, 최종 연산이 있는 경우에만 동작합니다.
다음 포스팅에서는 최종 연산에 대해 알아보겠습니다.
'Language > Java' 카테고리의 다른 글
[JAVA] Optional 클래스에 대해 알아보기 (0) | 2024.05.19 |
---|---|
[JAVA] Stream API에 대해 알아보기 _ Stream 최종 연산(집계) (4/5) (0) | 2024.05.18 |
[JAVA] Stream API에 대해 알아보기 _ Stream 생성 (2/5) (0) | 2024.05.16 |
[JAVA] Stream API에 대해 알아보기 (1/5) (0) | 2024.05.15 |
[JAVA] 큰 수 다루기 (BigInteger, BigDecimal) (0) | 2024.05.13 |