[Java] Java Stream
Java Stream
지난번에 이야기한 Java8의 핵심 기능, 자바 Optional에 이어서, 오늘은 Stream에 대해서 정리합니다.
Java Stream 정의
Java Stream은 배열이나 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있게 해주는 반복자입니다. 이전에는 Java Stream이 없었을 때는 Iterator이라는 반복자를 사용하였습니다.
- Java Iterator
ArrayList<Integer> list = new ArrayList<>(Array.asList(1, 2, 3));
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
int num = it.next();
System.out.print(num + " ");
}
// output : 1, 2, 3
- Java Stream
ArrayList<Integer> list = new ArrayList<>(Array.asList(1, 2, 3));
Stream<Integer> stream = list.stream();
stream.forEach(num -> System.out.print(num + " "));
// output : 1, 2, 3
Java Stream 특징
- 배열 또는 컬렉션 인스턴스에 함수 여러 개를 조합해서 원하는 결과를 필터링할 수 있으며 가공된 결과를 얻을 수 있습니다.
- 람다를 통해 코드를 간결하게 표현할 수 있습니다.
- 배열과 컬렉션을 통해 함수형으로 처리할 수 있습니다.
- 병렬처리가 가능합니다.
Java Stream 구조 및 사용법
스트림은 다음과 같은 절차로 사용할 수 있습니다.
- 스트림 생성 : 스트림 인스턴스 생성
- 중개 연산 : 필터링(filtering) 및 맵핑(mapping) 등으로 원하는 결과를 만들어가는 중간 과정
- 최종 연산 : 최종적으로 결과를 만드는 작업
스트림 생성
- 배열 스트림 :
Arrays.stream()
을 사용합니다.
int[] array = {1, 2, 3};
IntStream intStream = Arrays.stream(array);
- 컬렉션 스트림 : 인터페이스의 default method를 사용합니다.
List<Integer> list = Arrays.asList(1, 2, 3);
Stream<Integer> stream = list.streams();
Stream<Integer> parallelStream = list.parallelStream();
중개 연산
- Filter: 스트림 내 요소 중 조건에 맞는 것을 고릅니다.
List<String> arrary = Arrays.asList("apple", "banana", "melon");
Stream<String> stream = arrary.stream().filter(x -> x.contains("a"));
// output : ['apple', 'banana']
- Map : 스트림 내 요소들이 특정 로직 수행 후 새로운 스트림을 반환합니다.
List<Integer> list = Arrays.asList(1, 2, 3);
Stream<Integer> stream = list.stream().map(x -> x + 1);
// output : [2, 3, 4]
- flatMap : 여러 스트림을 하나의 스트림으로 합칩니다.
String[][] array = new String[][]{{"a1", "a2"}, {"b1", "b2"}, {"c1", "c2"}};
Stream<String> stream = Arrays.stream(arr).flatMap(s -> Arrays.stream(s));
// output : ["a1", "a2", "b1", "b2", "c1", "c2"]
- sorted : 정렬합니다.
List<Integer> list = Arrays.asList(1, 4, 3);
List<Integer> sortedList = list.stream().sorted().collect(Collectors.toList()); // 오름차순
// output : [1, 3, 4]
List<Integer> sortedList = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()); // 내림차순
// output : [4, 3, 1]
최종 연산
- count, min, max, sum : 갯수, 최소, 최대, 합
- forEach : 요소를 돌면서 실행합니다.
- collect : 스트림의 값들을 모을 수 있습니다. ex)
toMap()
,toSet()
,toList()
List<Integer> arr = Arrays.asList(1, 2, 3, 3, 4, 5, 5);
Set<Integer> set = arr.stream().collect(Collectors.toSet());
set.forEach(x -> System.out.print(x + " " ));
// output : 1 2 3 4 5
- reduce : 누적된 값을 계산합니다.
OptionalInt reduced =
IntStream.range(1, 4) // [1, 2, 3]
.reduce((a, b) -> {
return Integer.sum(a, b);
});
// output : 6 (1 + 2 + 3)
int reducedTwoParams =
IntStream.range(1, 4) // [1, 2, 3]
.reduce(10, Integer::sum);
// output : 16 (10 + 1 + 2 + 3)
}
마무리.
오늘은 간단하게 stream에 대해 알아보고 이를 사용한 예시를 사용하였습니다. 현업에서 stream과 optional, lambda식을 잘 쓰는 것은 클린 코드를 만드는데 좋은 스킬 중 하나임을 개발하면서 자주 느낍니다. 오늘 사용한 예제말고도 다른 예제는 찾아보면서 좋은 개발할 수 있으면 좋겠습니다.
감사합니다.
출처