Java Stream: 람다식과 메서드 참조로 목록 처리하기
Java 8의 Stream을 공부하면서 람다식과 메서드 참조를 함께 정리했습니다. 목록을 출력하고 조건에 맞는 값만 남긴 뒤 문자열을 숫자로 바꾸는 예제입니다.
비교자를 람다식으로 바꾸기
먼저 정렬 기준을 익명 클래스로 작성했습니다. 두 번째 값이 같으면 첫 번째 값으로, 다르면 두 번째 값으로 비교합니다.
당시 예제에서는 뺄셈으로 비교했습니다. 큰 정수끼리 빼면 오버플로가 날 수 있으므로 모든 정수 범위에 안전한 비교는 아닙니다.
Arrays.sort(arr, new Comparator<int[]>(){
@Override
public int compare(int[] o1, int[] o2) {
if (o1[1] == o2[1]) {
return o1[0] - o2[0];
}
return o1[1] - o2[1];
}
});Comparator는 추상 메서드가 하나인 함수형 인터페이스라서 람다식으로 구현할 수 있습니다. 비교 로직만 남기면 다음과 같습니다.
Arrays.sort(arr, (int[] o1, int[] o2) -> {
if (o1[1] == o2[1]) {
return o1[0] - o2[0];
}
return o1[1] - o2[1];
});메서드 참조로 변환 함수 전달하기
문자열을 정수로 바꾸는 함수는 Integer::parseInt로 전달할 수 있습니다.
str.stream().map(Integer::parseInt);이 줄은 변환 단계를 정의할 뿐 아직 변환을 실행하지 않습니다. Stream은 단순한 반복자나 즉시 실행되는 for문과 달리 map, filter 같은 중간 연산을 지연 실행하므로 collect, forEach 같은 최종 연산이 있어야 처리가 진행됩니다. 자세한 실행 방식은 Java 8 Stream API 문서에 있습니다. 아래 전체 예제에서는 collect까지 호출해 변환한 값을 목록으로 모았습니다.
전체 예제
0부터 9까지 두 방식으로 출력한 뒤 짝수만 남깁니다. 문자열 목록은 정수로 변환해 출력합니다. 마지막에는 문자열에 9가 포함된 값만 출력합니다.
package Java;
import java.util.*;
import java.util.stream.Collectors;
class Main {
public static void main(String[] args) {
ArrayList<Integer> arr = new ArrayList<>();
for (int i = 0; i < 10; i++) {
arr.add(i);
}
// forEach를 통해 리스트 요소의 개수 만큼 반복
arr.stream().forEach(s -> System.out.println(s));
System.out.println("=======================");
arr.stream().forEach(System.out::println);
System.out.println("=======================");
// 리스트의 2로 나눈 나머지 값이 0인 값을 필터링 -> forEach로 반복 -> System.out 의 println 메소드로 출력
arr.stream().filter(s -> s % 2 == 0).forEach(System.out::println);
System.out.println("=======================");
ArrayList<String> str = new ArrayList<>();
str.add("281");
str.add("182");
str.add("192");
// str의 요소룰 map을 통해 Integer 객체로 변환 -> collect를 통해 List 타입으로 변환 -> forEach를 통해 요소의 개수만큼 반복
// ::의 용도는 Integer 클래스의 메소드를 수행하는 메소드 참조
str.stream().map(Integer::parseInt).collect(Collectors.toList()).forEach(s -> System.out.println(s));
System.out.println("=======================");
// 9라는 문자열을 가진 요소를 필터링 -> 출력
str.stream().filter(s -> s.contains("9")).forEach(System.out::println);
}
}당시 기록한 출력은 다음과 같습니다.
0
1
2
3
4
5
6
7
8
9
=======================
0
1
2
3
4
5
6
7
8
9
=======================
0
2
4
6
8
=======================
281
182
192
=======================
192