티스토리 뷰
아래 소스는 Java8을 기준으로 작성되었습니다. 혹시 오타가 있거나 잘못 이해한 부분이 있으면 댓글로 적어주세요 :)
글(1) 에서 기본적으로 정의를 했다면 이번에는 어떻게 구체적으로 사용하는지 설명해보려고 한다.
기본적으로 인터페이스를 생성하면 다른 클래스에서는 아래와 같이 사용할 수 있다.
소스가 너무 길었음에도 람다를 사용하여 간편하게 만들었다.
파라미터를 사용하는 방법은 위와 같고, 2개 이상인 경우는 소괄호'()'를 붙여주면 된다.
또, 위에 소비형, 반환형으로만 이야기하였는데, 함수형 프로그래밍에서는 4가지 형식의 타입이 존재한다.
1. Function (파라미터를 받고 수행한 후 리턴값이 있다. 4번과 비슷하다. )
2. Consumer (파라미터를 받고 수행하고 리턴이 없다. 1, 3번이 이에 속하고, 파라미터가 2개 이상이면 BiConsumer라고 한다. )
3. Predicate (파라미터를 받아서 참,거짓을 리턴한다. )
4. Supplier (파라미터가 없고 리턴값이 있는 2번과 비슷하다. )
람다의 기본 구현 방법은 어느 정도 표현이 된 거 같고, 이제 Stream을 살펴보려 한다.
시작 부분은 모두 .stream()이지만 List가 아닌 다른 객체는 표현 방식이 이와 같다.
배열은 Arrays라는 자바 기본 클래스로 감싸서 스트림을 표현한다.
Enum은 EnumSet이라는 Set으로 변형하여 스트림을 표현한다.
Stream Class에서 사용하는 메소드는 많지만, 그 중 자주 사용되는 메소드를 보려 한다.
Optional 객체는 참조변수 값이 null일 가능성이 있을때 예외처리를 방지하기 위해 사용하는 객체이다.
메소드 | 수행 방식 | 리턴 타입 | 설명 |
forEach | Consumer | void | 가장 기본적인 for문 |
count | Supplier | long | Stream의 카운트(list.size()) |
filter | Predicate | Stream<T> | 필터링할 조건을 넣는다 예시) filter(a -> "abbo".equals(a.getNickname())) // 닉네임이 abbo인거로 필터링 |
map | Function | Stream<T> | Object 중 필요한 값으로 Stream 예시) map(a -> a.getBirth()) // 생일로 Stream |
peek | Consumer | Stream<T> | Object의 set을 하기위해 사용한다. 예시) peek(a -> a.setName("abbo")) // 모든 요소의 이름에 abbo |
reduce | BInaryOperator | Optional<T> | 값의 연산, 누적을 위해 사용한다. 예시) reduce(a -> a.getCount() % 3) // 3으로 나눈 나머지로 스트림 |
sorted | Supplier, Predicate | Stream<T> | 정렬 / 특정 조건으로 정렬 |
distinct | Consumer | Stream<T> | 중복 제거 |
max | Comparator | Optional<T> | 비교구문과 조건이 일치하는 최대값 1개 |
min | Comparator | Optional<T> | 비교구문과 조건이 일치하는 최소값 1개 |
findAny | Supplier | Optional<T> | 아무거나 1개 |
findFirst | Supplier | Optional<T> | 스트림 첫번째 요소 |
orElse | Supplier | Optional<T> | find 후 조건에 만족하는 값이 없는 경우 예시) filter(a -> a > 3).findFirst().orElse(4) |
allMatch | Predicate | boolean | 전부 만족하는지 체크 |
anyMatch | Predicate | boolean | 하나라도 만족하는지 체크 |
noneMatch | Predicate | boolean | 만족하는값이 없는지 |
collect | Collector, Supplier | R | 1.최종 스트림된 결과를 List, Set, Collection으로 조합한다. 예시) collect(Collectors.toList()) or collect(Collectors.toSet()) or collect(Collectors.toCollection(colFactory)) 2. 통계용으로 사용한다. 예시) counting(), summingInt(), averagingInt(), maxBy() 등 3. joining() 을 써서 문자열로 결합한다. 4. 그룹화 용도로 사용한다. partitioningBy(조건) 을 써서 요소를 2분할 한다. 예시) Map<Boolean, Abbo> map = stream.collect(partitioningBy(Abbo::isMale)); or groupingBy(조건, 반환형)으로 그룹화한다. 예시) Map<Integer, List<ABBO> map = stream.collect(groupingBy(ABBO::getBirthYear, toList())); |
(Optional에 대한 설명은 여기에 적어두었으니 확인해주세요.)
수행 방식은 람다 표현식의 4가지 타입 중 1개 또는 연산자가 들어갈 수 있다.
여기서 리턴 타입이 Stream<T> 라는 것은 .filter(~).map(~) 처럼 Chaining이 가능한 것을 의미한다.
팁으로 Match가 들어간 메소드는 대부분 filter이후 사용하면 좋다.
순서는 선언되는 것에 맞춰서 진행이 되고, 중간연산 들이 수행이 된 후 최종 연산이 수행 된다.
최종 연산에는 sort(), distinct() 같은 것이 있다.
또, Stream 뿐만 아니라 기본형 스트림으로 IntStream, LongStream, DoubleStream 등이 있으니 연산에 더 수월하게 사용도 가능하다.
Thread의 개념을 알고 있다면 병렬 스트림(parallel)도 사용 가능하다.
자세한 사용법은 시간이 가능하다면 올리도록 하겠다..(한 번씩 전부 사용하는게 가능할까 의문)
'Server' 카테고리의 다른 글
[Java] 엑셀 변환 (0) | 2019.12.03 |
---|---|
[Java] ORM과 JPA, 그리고 Hibernate (0) | 2019.11.28 |
[Java] NPE와 Optional Class (1) | 2019.10.26 |
[Java] Lambda와 Stream(1) (2) | 2019.10.15 |
REST의 정체는? (1) | 2019.10.15 |
[Spring] Annotation과 MVC (1) | 2019.09.17 |