Search
Duplicate

Java8의 StreamAPI 정리

생성일
2023/01/31 11:48
태그
공개여부

스트림 Stream

자바8 에서 추가된 스트림은 람다를 활용할 수 있는 기술 중 하나이다.
스트림은 데이터의 흐름이다.
배열 또는 컬렉션 인스턴스에 함수 여러개를 조합해서 원하는 결과를 필터링하고 가공된 결과를 얻을 수 있다. 또한 이를 람다를 이용해서 코드의 양을 줄이고 간결하게 표현 가능하다. 즉, 배열과 컬렉션을 함수형으로 처리할 수 있다.

스트림의 특징

1. 데이터 소스를 변경하지 않는다.

스트림은 데이터를 읽기만 한다. 데이터 소스를 변경하지 않는다.
List<String> list = Arrays.asList(new String[]{"a","c","d","b"}); List<String> list2 = list.stream().sorted().collect(Collectors.toList());
Java
복사
list → {a,c,d,b}
list2 → {a,b,c,d}
원본을 유지한 채 새로운 컬렉션을 만들어내야 할 때 유용함.

2. Stream 객체는 1회만 사용이 가능하다.

Stream<String> listStream = list.stream(); List<String> list2 = listStream.sorted().collect(Collectors.toList()); ... listStream.forEach(System.out::println);
Java
복사
보통 stream() 함수를 뒤에 스트림 연산을 그대로 붙여서 사용한다.

3. 반복 처리

보통 반복 처리를 위해서는 반복문을 사용하거나 컬렉션의 forEach를 사용한다. 그럼 코드가 길어지고 로직을 직접 짜야하지만 Stream을 사용하면 Stream 내부에 구현되어 있는 연산들로 해결할 수 있다.

4. 병렬처리

하나의 작업을 둘 이상의 작업으로 잘게 나눠서 동시에 진행 하는 것을 병렬처리라고 하는데 쓰레드를 이용해 많은 요소들을 빠르게 처리할 수 있다.
기본적으로 병렬 연산을 처리하지 않는다. 하지만 parallel() 메소드를 호출할 경우 연산을 병렬로 수행하게 된다.
List<String> list = Arrays.asList(new String[]{"a","c","d","b"}); list.stream().parallel().forEach(System.out::println);
Java
복사
이렇게 출력할 경우 a c d b 순서대로 출력되는것이 아니라 뒤죽박죽 출력된다.

주요 스트림 연산

1.
of
컬렉션에서는 stream() 함수를 호출하면 스트림 객체가 생성된다. 하지만 데이터가 컬렉션 형태가 아니라 그냥 데이터 그대로 있는경우에는 of()와 같은 스트림 static 함수를 이용해서 stream 객체로 만들어줘야 한다.
2.
sorted
정렬 연산. 정렬을 하고나면 정렬된 데이터에 다른 스트림을 다시 반환하므로 정렬된 데이터들을 가지고 스트림 연산을 이어서 수행할 수 있다(중간 연산). 기본은 오른차순 정렬이고 만일 읽어들인 데이터가 Map이나 별도 필드를 가지고 있는 커스텀 객체일 경우 어떤 필드로 정렬해야하는지 정의를 위해 Comparator.comparing(객체:필드)로 기준 필드를 정의해줘야 한다. 내림 차순은 Comparator.comparing(객체:필드).reserved()를 통해 할 수 있다.
3.
forEach
스트림이 읽어들인 데이터 각각에 대해 수행해야 하는것이 있을 때 사용한다.
Collection forEach VS Stream forEach 리소스 면에서 Collection forEach가 더 효율적이지만, 원본데이터를 건드리지 않는 다는 점에서 Stream forEach의 장점이 있다.
4.
map
forEach 와 비슷하지만, map()은 스트림을 반환해서 반환 받은 스트림 객체를 이용해서 새로운 컬렉션을 만들 수 있다는 것이다. forEach()는 함수 안에서 기능을 수행하면 끝나는 것과 달리 map()을 계속해서 스트림 연산을 이어나갈 수 있는 것이다.
5.
flatMap
flatMap은 컬렉션 안에 컬렉션이 있어서 스트림안에 스트림을 생성해서 스트림 연산을 사용해야할 때 유용하게 사용할만한 스트림 연산이다.
6.
filter
말 그대로 데이터들을 가지고 필터링 하는 것이다. 특정 설정한 조건에 맞는 데이터만 모아서 스트림을 반환한다.
filter() 연산 안에서는 데이터를 통해서 true/false를 반환하면 된다.
7.
collect
collect() 는 스트림을 통해 컬렉션을 만들어주는 연산이다. 즉, 스트림으로 새로운 컬렉션을 만들어서 반환해준다.
collect 연산 안에는 Collectors를 넣어서 어떤 컬렉션으로 만들지 정의한다.
8.
reduce
reduce()는 최종 연산으로 스트림 안의 요소들을 소모하면서 연산을 수행한다. 결과값으로 연산의 결과 값을 내놓는다.
스트림에 여러 데이터가 들어 있을 경우 reduce() 연산은 맨 처음에는 데이터1, 데이터2 로 reduce() 안에 정의해놓은 연산을 수행한다. 그리고 데이터 끝까지 모든 연산을 수행한 후 최종 결과를 반환한다. 즉, 처음 요소 2개로 연산한 결과 값과 그 다음 요소를 연산하고 또 그 결과 값과 다음 요소를 연산하는 식으로 연산이 데이터 순서대로 이어진다고 생각하면 된다.