====== Java 8 Stream ====== * [[http://www.javacodegeeks.com/2015/07/java-performance-tutorial-how-fast-are-the-java-8-streams.html|Java performance tutorial – How fast are the Java 8 streams?]] * [[http://www.javacodegeeks.com/2015/07/java-se-8-new-features-tour-processing-collections-with-streams-api.html|Java SE 8 new features tour: Processing Collections with Streams API]] * [[http://www.javacodegeeks.com/2015/09/stream-performance.html|Stream Performance]] * [[http://www.slideshare.net/ssuser1fb4cf/api-42194312|Java 8 Stream API]] ===== Stream for Iterable ===== * [[http://stackoverflow.com/questions/23932061/convert-iterable-to-stream-using-java-8-jdk|Convert Iterable to Stream using Java 8 JDK]] StreamSupport.stream(iterable.spliterator(), false) .filter(...) .moreStreamOps(...); ===== List> 같은 컬렉션의 컬렉션 Flatten ===== * [[http://stackoverflow.com/questions/25147094/turn-a-list-of-lists-into-a-list-using-lambdas|java - Turn a List of Lists into a List Using Lambdas - Stack Overflow]] List> list = ... List flat = list.stream() .flatMap(List::stream) .collect(Collectors.toList()); ===== Null safe stream ===== public static Stream asStream(Collection collection) { return Optional.ofNullable(collection) .map(Collection::stream) .orElse(Stream.empty()); } public static Stream asStream(T[] array) { return Optional.ofNullable(array) .map(Arrays::stream) .orElse(Stream.empty()); } public static Stream> asStream(Map map) { return Optional.ofNullable(map) .map(kvMap -> kvMap.entrySet().stream()) .orElse(Stream.empty()); } ===== Collectors.toMap ===== * ''Collectors.toMap(key function, value function[, mergeFunction])'' * 보통은 Key 하나에 값이 하나 일 때 사용. * Key 하나에 값이 여러개가 나오는 충돌에 대해 ''merge'' 전략을 제공해줘야 할수도 있다. * 원래 ''HashMap'' 는 ''null'' value를 허용하지만, ''Collectors.toMap''에서는 이게 허용이 안된다. * 이유는 해당 구현 내부적으로 호출하는 ''HashMap.merge()'' 메소드에서 이를 허용하지 않기 때문. ===== Collectors.groupingBy ===== * ''Map'' 을 만들면서 다시 Collectors 의 결과를 값으로 넣는다. 보통은 키 하나에 값이 여러개가 나올 때 사용. ===== distinct by key ===== * 객체의 특정 field / property 를 통해 ''distinct''를 하려면, * [[https://stackoverflow.com/a/27872852/1051402|별도 Predicate 선언방식]] public static Predicate distinctByKey(Function keyExtractor) { Map seen = new ConcurrentHashMap<>(); // parallel stream에서 호출할까봐 이렇게 한듯. return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } persons.stream().filter(distinctByKey(p -> p.getName()); * ''toMap''이용 // 특정 Key 필드로 Map을 만들되 중복 값은 모두 무시 persons.stream() .collect(toMap(Person::getName, Function.identity(), (p1, p2) -> p1)) .values(); ===== parallelStream ===== * [[https://dzone.com/articles/should-i-parallalise-streams|Should I Parallelize Java 8 Streams?]] * ''parallelStream''은 작업 분배 오버헤드가 발생하기 때문에 CPU 연산작업만 병렬화 할경우에는 오히려 느려지는 경향이 있다. * DB 조회/API 호출 처럼 순차보다는 병렬이 확실히 더 확실할 때 빼고는 ''parallelStream''은 사용하지 않는게 낫다. * 그리고 Thread 안정성도 보장해줘야한다. * 따라서 성능테스트로 완벽하게 더 좋은 성능이 보장되지 않는다면, 그냥 기본적으로 일반 스트림을 사용해야 한다. ===== unmodifiable, immutable collection ===== * [[https://medium.com/@hithacker/producing-immutable-list-from-stream-in-java-8-97f96ae3b04f|Producing immutable list from stream in Java 8 - Hiren Thacker - Medium]] List immutableBlues = shapes.stream() .filter(s -> s.getColor() == BLUE) .collect(collectingAndThen(toList(), Collections::unmodifiableList)) * [[https://www.baeldung.com/java-stream-immutable-collection|Collect a Java Stream to an Immutable Collection]] [[java:guava|Guava]] 21 부터 Collector 가 추가됨. List list = IntStream.range(0, 9) .boxed() .collect(ImmutableList.toImmutableList()); // Generic Immutable Collection collector 만들기. 컬렉션 구현체를 원하는대로 선택 public static > Collector> toImmutableList( Supplier supplier) { return Collector.of( supplier, List::add, (left, right) -> { left.addAll(right); return left; }, Collections::unmodifiableList); } // 사용예 - LinkedList 구현을 unmodifiable로 감싸기 List givenList = Arrays.asList("a", "b", "c", "d"); List result = givenList.stream() .collect(MyImmutableListCollector.toImmutableList(LinkedList::new)); * ''ImmutableMap.toImmutableMap()'' 도 사용가능. ''Collectors.toMap'' 과 유사 ===== 참고 ===== * [[https://www.baeldung.com/java-predicate-chain|Java 8 Predicate Chain | Baeldung]] * [[https://www.baeldung.com/java-stream-reduce|Guide to Stream.reduce() | Baeldung]]