현재 공부하고 있는 도서의 Stream API 에 대한 자세한 설명이 나와 있어서, 같은 주제로 계속 블로깅을 하고 있습니다. 


하지만 대략적인 부분이 끝이 난 것 같습니다. Stream API 소개는 이번 포스팅이 마지막입니다.

지난 Stream API 가 궁금하다면, 하단 글들을 참고해주세요. :-)



오늘 포스팅은 보통 전공 과목에서 흔히 말하는 기타 기능에 대해 알아보려고 합니다. 그러나 유용할 수 있죠? :-)


1. 숫자형 스트림으로 변환


람다를 포스팅할 때도 있었지만, 스트림 역시 원시타입의 스트림을 지원합니다. 보다 더 정확히 말하면, 숫자들에 대한 스트림을 지원하며 이 기본형 특화 스트림들은 sum, max, min 등 자주 사용하는 리듀싱 메소드를 제공해줍니다.


숫자 스트림을 사용하기 위해서는 map 의 파생 메소드인 mapToInt, mapToDouble, mapToLong 등의 메소드를 사용해야 합니다.


예제부터 한번 봐볼까요?


1
2
3
4
5
6
7
8
9
List<Integer> numberList = Arrays.asList(1,2,3,4,5,6);
    
System.out.println(
        numberList.
            stream().
            mapToInt(Integer::intValue).
            sum());
 
// 출력 21
cs


간단한 Integer Collection 객체의 stream 에서 int value 의 stream 얻기 위해 mapToInt 메소드를 사용하였으며(언박싱), 리듀스 메소드 중 하나인 sum 을 사용하였습니다.


추가적으로 또다른 리듀싱 메소드인 max나 min 은 Optional 상태로 데이터가 제공됩니다. 컬렉션이 비어있는 상태에서 max 나 min 의 값이 무조건 존재한다는 것을 보장할 수 없기 때문이죠.



2. 숫자 범위 스트림


JAVA8 에서는 숫자형스트림에서 특정 범위안의 숫자 집합을 출력해주는 정적메소드인 rangerangeClosed 를 제공해줍니다. 두 메소드 모두 범위에 대한 인수를 받으며, 차이는 시작값과 종료값이 결과에 포함하는 여부입니다. (range 의 경우 결과에 포함되지 않습니다.)


사용예제는 다음과 같습니다. 아래 예제는 숫자 Stream 을 이용하여, 피타고라스의 수를 구하는 쿼리입니다.


1
2
3
4
5
6
7
IntStream.rangeClosed(1,100).
        boxed().
        flatMap(a -> IntStream.
                        rangeClosed(a, 100).
                        mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a *+ b * b)})).
        filter(v -> v[2]%1 == 0).
        forEach(v -> System.out.println(v[0+ " " + v[1+ " " + v[2]));
cs


flatMap 을 통해, 두 개의 숫자 스트림을 엮었습니다. 첫번째 범위에서는 Stream 연산의 결과를 객체로 받기 위해 boxed 메소드를 사용하였습니다. boxed 객체를 사용하지 않으면, 오직 중간연산 결과로 숫자타입의 스트림밖에 생산할 수 없습니다. (왜냐하면 IntStream 은 숫자 스트림이기 때문이죠. ㅡㅡ^)



3. 스트림 만들기


컬렉션이나 배열은 다음과 같이 임의의 값으로 데이터를 만들 수 있습니다.


1
2
String[] dataArray = new String[]{"남두현""윤석진""성지윤""오진명"}; 
List<String> dataList = Arrays.asList(dataArray);
cs


스트림 역시 임의의 값으로 스트림 만들기가 가능합니다. 꼭 컬렉션 클래스의 stream 키워드를 쓸 필요는 없는 것이죠. ㅡㅡ^


1
2
3
4
String[] dataArray = new String[]{"남두현""윤석진""성지윤""오진명"}; 
        
Stream<String> ofStream = Stream.of("남두현""윤석진""성지윤""오진명");
Stream<String> arrayStream = Arrays.stream(dataArray);
cs



4. 고정되지 않은 크기의 스트림 만들기


여태까지 Stream은 고정된 크기의 컬렉션을 통해서 만들곤 했습니다. 그러나 특정 Function, Supplier 타입의 메소드 레퍼런스 (람다 포함) 를 통해 무한한 Stream 을 만들 수 있습니다.


1
2
3
4
5
// iterate 는 Function type 람다를 사용 
Stream.iterate(0, n -> n + 2).forEach(System.out::println);
        
// generate 는 Supplier type 메소드 레퍼런스 사용
Stream.generate(Math::random).forEach(System.out::println);    
cs


만들 수 있는 key-word 메소드는 iterate 와 generate 로 보통 limit 로 제한을 두어 사용하곤 합니다. 제한을 두지 않은 스트림을 언바운드 스트림(Unbounded Stream) 이라 하며, 특정 로직에서 무한한 결과 때문에 제대로된 결과를 얻을 수 없을 지도 모릅니다. 

(그러나 위 예제 에서는 무한한 숫자가 출력이 될 것입니다. 컬렉션과 달리 Stream 은 즉시 생산을 하는 것이 특징이기 때문이죠. ㅡㅡ^)


것으로 Stream API 활용과 관련된 주제는 끝났습니다.


다음 포스팅 부터는 Stream 을 통한 데이터 수집과 관련된 주제로 진행을 하게 될 것 같습니다. 

(스포일러를 하자면, 언제나 최종 연산을 구할 때 사용했던 Collector 와 관련된 이야기 입니다. ^^)



자바 8 인 액션
국내도서
저자 : 라울-게이브리얼 우르마(RAOUL-GABRIEL URMA),마리오 푸스코(MARIO FUSCO),앨런 마이크로프트(ALAN MYCROFT) / 우정은역
출판 : 한빛미디어 2015.04.01
상세보기


반응형
Posted by N'