안녕하세요. 블로그 주인인 초보프로그래머입니당.


오랜만의 블로그 포스팅입니다.  개인적으로 바쁜 일이 있어서(곧 회사내에서 출시를 하기 때문에 버그를 열심히 잡았죠... ㅡㅡ^), 오랜만에 공부를 해보고 내용을 정리하게 되었습니다.


솔직히 블로그할 시간은 있긴 했지만, 게을러지다보니 공부하게 되는 것이 쉽지가 않네요.


하지만 책을 산 것이 아깝고, 곧 진행했던 안드로이드 프로젝트에도 함수형 프로그래밍의 결실을 시도해봐야하니(RxJava or Android N) 다시 한번 붙잡게 되었습니다.


그런 의미에서 오늘은 계속 진행하던 Stream API 의 활용에 대해 보고자 합니다. 

Stream API에 대해 처음보게 된다면 이 곳을 먼저 확인해주세요.



이전에 Stream API를 소개할 때, 컨테이너(Collection)의 활용을 질의 형태로 작성할 수 있다고 언급했었는데요. 마치 고수준 언어인 SQL을 사용하듯 말이죠. (Collection 객체를 테이블이라고 본다면, 질의를 통해 어떤 결과를 얻는다 생각하면 좋겠네요? ㅡㅡ^)


오늘은 그 중 필터링과 슬라이싱(즉 검색.. ㅡㅡ^)을 해보려 합니다.


1. 필터링

SQL의 where 절과 같은 역할입니다. Collection 객체 중 프리디케이트(Predicate)에 부합하는 객체들을 따로 추출하는 역할을 합니다. 그 메소드는 이전부터 많은 예제로 사용되었던 filter 입니다. 


몸풀기로 시작해보겠습니다.


1
2
3
4
5
6
7
8
9
List<Integer> numberList = Arrays.asList(22345688910);
 
for (Integer a : numberList.stream().filter(a -> a % 2 == 0).
                collect(Collectors.toList())) {
    System.out.println(a);
}
 
console result : [2,2,4,6,8,8,10]
 
cs


filter 메소드를 이용하여, 짝수만을 조회하였습니다. SQL로 치자면, 이정도??


1
SELECT number FROM NUMBERLIST WHERE number % 2 = 0;

cs


2. 고유 요소 필터링

위의 결과 중, 중복된 결과가 있습니다. 원하는 결과가 중복된 값이 없기를 바란다면 distinct 메소드를 사용해주면 됩니다.


1
2
3
4
5
for (Integer a : numberList.stream().filter(a -> a % 2 == 0).
                distinct().collect(Collectors.toList())) {
    System.out.println(a);
}
 
cs


생각해보면 SQL에서 DISTINCT 를 사용하여, 고유 결과를 출력할 수 있다는 것을 알고 있습니다.


1
SELECT DISTINCT number FROM NUMBERLIST WHERE number % 2 = 0;
cs


3. 결과값 제한과 스킵

보통 게시판을 만들 때, limit offset 등을 사용하여 페이징 처리를 하곤 합니다. 왜냐하면 많은 데이터를 한번에 다 보여줄 수도 없거니와, 사용도 불편하기 때문이죠.


Stream API에서는 limit offset 과 같은 역할을 해줄 수 있는 메소드 역시 가지고 있습니다.


일단 Stream을 잘 살펴보면, limit 라는 메소드를 가지고 있습니다. 아래 코드는 Stream의 결과 중, 3개를 반환하는 메소드입니다.


1
2
3
numberList.stream().filter(a -> a % 2 == 0).distinct().limit(3).forEach(System.out::println);
 
console result : [2,4,6]
cs


재미있는 점은 limit를 사용하지 않은 결과보다, limit의 파라미터 값이 크더라도 에러를 출력하지 않습니다. 이 점은 우리가 최대 몇개를 가져온다라는 비지니스 로직을 구현할 때, 방어코드를 할 필요가 없어졌음을 말합니다.


마지막으로 skip을 이용하여, 요소를 건너뛸 수 있습니다. 예를들어 3번째 결과부터 2개 출력이라 하면 이렇게 응용을 할 수 있습니다.


1
2
3
numberList.stream().filter(a -> a % 2 == 0).distinct().skip(3).limit(2).forEach(System.out::println);
 
console result : [8,10]
cs


skip역시 입력받는 파라미터에 대해 방어코드를 할 필요가 없습니다. 조건에 만족하지 못한다면 빈 배열을 출력합니다.



오늘 포스팅에서는 Stream API를 이용한 필터 및 슬라이싱하는 방법을 알아봤습니다. 


어느정도 함수형 프로그래밍의 감이 오시나요? 


오늘 포스팅으로 부터 알 수 있는 점은 함수형 프로그래밍으로 비지니스 로직을 구현 시,


1. 간편하고, 직관적인 선언형 위주의 구현


2. 방어코드 없이, 오류가 적은 코드의 구현


이라는 장점을 볼 수 있었음을 알 수 있었습니다.




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


반응형

'개발이야기 > 함수형 프로그래밍' 카테고리의 다른 글

Stream API 활용편3 (검색과 매칭)  (0) 2017.01.18
Stream API 활용편2 (매핑)  (0) 2016.08.27
Stream과 Collection 차이  (0) 2016.08.04
Stream API  (0) 2016.08.03
람다 조합  (0) 2016.08.02
Posted by N'