-
[Java] java8 streamJAVA 2021. 12. 17. 00:54
java8부터 지원이 된 stream은 람다함수형식으로 간결하고 직관적으로 요소들을 처리가 가능한 기능이다.
이러한 stream을 이용해 for문 등 직관적이지 않은 처리들을 깔끔하게 처리할 수 있다.
Stream의 구조
stream의 구조는 크게 세가지로 볼 수 있다.
1. stream의 생성
2. 중개 연산
3. 최종 연산
세가지로 구성되있으며, 중개연산은 연산결과를 stream형태로 반환하기 때문에 연속적으로 사용할 수 있다.
대략적인 구조는
데이터소스객체집합.stream생성().중개연산().최종연산();
이다.
Stream 생성
스트림 api는 다음과 같은 다양한 종류의 소스들에 사용할 수 있다.
1. 컬렉션
2. 배열
3. 가변 매개변수
4. 지정된 범위의 연속된 정수
5. 특정 타입의 난수
6. 람다 표현식
7. 파일
8. 빈 스트림
중개 연산
중개 연산은 stream을 받아 stream형식으로 리턴하기 때문에 중개 연산을 연속으로 사용할 수 있다.
stream의 중개연산은 필터-맵(filter-map)기반의 api를 사용함으로서 지연(lazy) 연산을 통해 성능을 최적화할 수 있다.
대표적인 중개 연산들은
1. stream 필터링 : filter(), distinct()
2. stream 변환 : map(), flatMap()
3. stream 제한 : limit(), skip()
4. stream 정렬 : sorted()
5. stream 연산 결과 확인 : peek()
예시
ArrayList<Int> list = new ArrayList<>(Arrays.asList(1, 5, 3, 5, 4, 5)); //distinct 중복 제거 list.stream().distinct().forEach(System.out::print); // 1534 //filter 해당하는것만 필터링 list.stream().filter(n -> n % 2 != 0).forEach(e -> System.out.print(e + " ")); // 1 5 3 5 5 ArrayList<String> list = new ArrayList<>(Arrays.asList("Drogba", "Essien", "Terry", "Lampard")); //map 스트림의 요소들을 인수로 전달하여, 반환값들로 새로운 스트림을 변환 list.stream().map(String::toUpperCase()).forEach(System.out::println); // DROGBA ESSIEN TERRY LAMPARD ArrayList<String> list = new ArrayList<>(Arrays.asList( "I love Drogba", "I want to be Essien", "Terry is nice guy", "Lampard is best coach")); //flatmap 이차배열이나, 여럿문자열이 저장된 스트림을 단일스트림으로 변환 list.stream().map(String::toUpperCase()).forEach(System.out::print); //IloveDrogbaIwanttobeEssienTerryisnoceguyLampardisbestcoach ArrayList<Int> list = new ArrayList<>(Arrays.asList(1, 5, 3, 5, 4, 5)); //limit 앞요소 제거 list.stream().skip(2).forEach(System.out::print); // 3545 //filter 뒷요소 제거 list.stream().limit(3).forEach(System.out::print); // 153
최종 연산
최종 연산은 앞서 중개 연산을 통해 만들어진 stream에 있는 요소들에 대해 마지막으로 각 요소를 소모하며 최종 결과를 보여준다. 즉 지연(lazy)되었던 모든 중개연산들이 최종 연산 시에 모두 수행된다. 이렇게 최종 연산시에는 모든 요소를 소모한 해당 stream은 더이상 사용할수없다.
대표적인 최종연산 메소드들은 다음과 같다.
1. 요소의 출력 : forEach()
2. 요소의 소모 : reduce()
3. 요소의 검색 : findFirst(), findAny()
4. 요소의 검사 : anyMatch(), allMatch(), noneMatch()
5. 요소의 통계 : count(), min(), max()
6. 요소의 연산 : sum(), average()
7. 요소의 수집 : collet()
예시
//findFirst(), findAny() output 형식 Optional ArrayList<String> list = new ArrayList<>(Arrays.asList("넷", "둘", "하나", "셋")); Optional<String> first = list.stream().filter(s -> s.stratsWith("넷")).findFirst(); //first.get() -> 넷 Optional<String> any = list.stream().filter(s -> s.stratsWith("넷")).findAny(); //any.get() -> 넷 //findFirst, findAny 차이 -> findAny는 병렬처리 첫번째값 리턴으로 매 리턴마다 값이 다를 수 있다. //allMatch(), anyMatch(), noneMatch() output 형식 boolean ArrayList<Int> list = new ArrayList<>(Arrays.asList(3, 7, 5, 4, 4, 2, 9)); boolean result = list.stream().allMatch(a -> a%2 == 0); //false 모든값이 해당하면 true boolean result = list.stream().anyMatch(a -> a%2 == 0); //true 해당값 하나라도 있으면 true boolean result = list.stream().noneMatch(a -> a%6 == 0); // true 모든값이 해당되지 않으면 true //collect() ArrayList<Int> list = new ArrayList<>(Arrays.asList(3, 7, 5, 4, 4, 2, 9)); List<String> list = list.stream().filter(n -> n % 2 ! = 0).collect(Collectors.toList()); // 스트림을 리스트로 변환 //Collectors 클래스의 partitioningBy() ArrayList<String> list = new ArrayList<>(Arrays.asList("넷", "둘", "하나", "셋")); //해당 stream의 각 요소별 글자 수에 따라 홀수와 짝수로 나누어 저장 Map<Boolean, List<String>> partition = list.stream().collect(Collectors.partitioningBy(s -> (s.length() % 2) == 0)); List<String> oddLengthList = patition.get(false);//넷, 둘, 셋 List<String> evenLengthList = patition.get(true);//하나
'JAVA' 카테고리의 다른 글
[Java]Optional 활용법 (0) 2021.12.17 [Java] Optional (0) 2021.12.17 [Java] 메소드 참조(method reference) (0) 2021.12.16 [JAVA] 람다식 (lamda Expression)와 함수형 인터페이스(Functional Interface) (0) 2021.10.04 [JAVA] 익명클래스(Anonymous class) (0) 2021.10.03