import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; public class MyListCollector<T> implements Collector<T, List<T>, List<T>>{ @Override public Supplier<List<T>> supplier() { return ArrayList<T>::new; } @Override public BiConsumer<List<T>, T> accumulator() { // return ArrayList<T>::add; return List::add; } @Override public BinaryOperator<List<T>> combiner() { return null; } @Override public Function<List<T>, List<T>> finisher() { return null; } @Override public Set<Characteristics> characteristics() { return null; } }
import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import static java.util.stream.Collector.Characteristics.CONCURRENT; import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH; import static java.util.stream.Collector.Characteristics.UNORDERED; public class MySetCollector<T> implements Collector<T, Set<T>, Set<T>> { @Override public Supplier<Set<T>> supplier() { System.out.println("supplier"); return HashSet<T>::new; } // 如果return HashSet<T>::add,那么會編譯報錯,原因在於 // 如果這里return的是HashSet,而supplier方法返回的是TreeSet // 那么顯然,中間用於累積的容器的類型二者是不一致的;就會出現問題 // 如果這里使用了Set::add,即接口類型,那么它就會兼容於supplier // 所返回的容器類型 // 總之:這里return的類型必須要與泛型的類型保持完全一致 @Override public BiConsumer<Set<T>, T> accumulator() { System.out.println("accumulator"); // return Set<T>::add; return (set, item) -> { System.out.println(item + ", " + set + ", " + Thread.currentThread().getName() ); set.add(item); }; } @Override public BinaryOperator<Set<T>> combiner() { System.out.println("combiner"); return (set1, set2) -> { set1.addAll(set2); return set1; }; } @Override public Function<Set<T>, Set<T>> finisher() { System.out.println("finisher"); return Function.identity(); // 對於IDENTITY_FINISH來說,該方法可以直接拋出異常,該方法實際上並不會被調用 // throw new UnsupportedOperationException(); } // 該方法會被調用2次,分別用於確定UNORDERED與IDENTITY_FINISH @Override public Set<Characteristics> characteristics() { System.out.println("characteristics"); return Collections.unmodifiableSet(EnumSet.of(IDENTITY_FINISH, CONCURRENT, UNORDERED)); } public static void main(String[] args) { List<String> list = Arrays.asList("hello", "world", "welcome", "hello", "a", "b", "c", "d", "e", "f", "g", "aa", "bb", "cc", "dd", "ee", "ff", "gg", "hh", "ii"); Set<String> preSet = new HashSet<>(); preSet.addAll(list); System.out.println(preSet); Set<String> set = preSet.stream().parallel().collect(new MySetCollector<>()); System.out.println("---------------"); System.out.println(set); // System.out.println(Runtime.getRuntime().availableProcessors()); } }
import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; public class MySetCollector2<T> implements Collector<T, Set<T>, Map<T, T>> { @Override public Supplier<Set<T>> supplier() { System.out.println("supplier invoked!"); // 串行流調用時,只會生成一個HashSet // 並行流調用時,每個線程都會生成一個HashSet /** * * A a1 = supplier.get(); * accumulator.accept(a1, t1); * accumulator.accept(a1, t2); * R r1 = finisher.apply(a1); // result without splitting * * A a2 = supplier.get(); * accumulator.accept(a2, t1); * A a3 = supplier.get(); * accumulator.accept(a3, t2); * R r2 = finisher.apply(combiner.apply(a2, a3)); // result with splitting */ return () -> { System.out.println("~~~~~~~~~~~~~~~~~"); return new HashSet<T>(); }; // return HashSet<T>::new; } @Override public BiConsumer<Set<T>, T> accumulator() { System.out.println("accumulator invoked!"); return (set, item) -> { System.out.println("accumulator, " + set + ", " + Thread.currentThread().getName()); set.add(item); }; } @Override public BinaryOperator<Set<T>> combiner() { System.out.println("combiner invoked!"); return (set1, set2) -> { System.out.println("combiner, " + set1 + ", " + set2); set1.addAll(set2); return set1; }; } @Override public Function<Set<T>, Map<T, T>> finisher() { System.out.println("finisher invoked!"); return set -> { System.out.println("finisher, " + set); Map<T, T> map = new TreeMap<>(); set.stream().forEach(item -> map.put(item, item)); return map; }; } @Override public Set<Characteristics> characteristics() { System.out.println("characteristics invoked!"); // return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED, Characteristics.IDENTITY_FINISH)); return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED, Characteristics.CONCURRENT)); } public static void main(String[] args) { System.out.println(Runtime.getRuntime().availableProcessors()); List<String> list = Arrays.asList("hello", "world", "welcome", "hello", "a", "b", "c", "d", "e", "f", "g"); Set<String> set = new HashSet<>(); set.addAll(list); System.out.println("set: " + set); System.out.println("----------"); //串行執行時combiner並不會得到調用,combiner只在並行流時會得到調用 // Map<String, String> map = set.stream().parallel().sequential().parallel().collect(new MySetCollector2<>()); Map<String, String> map = set.parallelStream().collect(new MySetCollector2<>()); System.out.println(map); } }
import java.util.Arrays; import java.util.Comparator; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Map; import java.util.Optional; import static java.util.stream.Collectors.averagingInt; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.maxBy; import static java.util.stream.Collectors.minBy; import static java.util.stream.Collectors.partitioningBy; import static java.util.stream.Collectors.summarizingInt; import static java.util.stream.Collectors.summingInt; import static java.util.stream.Collectors.toList; public class StreamTest1 { public static void main(String[] args) { Student student1 = new Student("zhangsan", 80); Student student2 = new Student("lisi", 90); Student student3 = new Student("wangwu", 100); Student student4 = new Student("zhaoliu", 90); Student student5 = new Student("zhaoliu", 90); List<Student> students = Arrays.asList(student1, student2, student3, student4, student5); // List<Student> students1 = students.stream().collect(toList()); // students1.forEach(System.out::println); // System.out.println("------------"); // // // System.out.println("count: " + students.stream().collect(counting())); // System.out.println("count: " + students.stream().count()); // System.out.println("------------"); // // // students.stream().collect(minBy(Comparator.comparingInt(Student::getScore))).ifPresent(System.out::println); // // students.stream().collect(maxBy(Comparator.comparingInt(Student::getScore))).ifPresent(System.out::println); // // System.out.println(students.stream().collect(averagingInt(Student::getScore))); // // System.out.println(students.stream().collect(summingInt(Student::getScore))); // // IntSummaryStatistics intSummaryStatistics = students.stream().collect(summarizingInt(Student::getScore)); // System.out.println(intSummaryStatistics); // System.out.println("------------"); // // System.out.println(students.stream().map(Student::getName).collect(joining())); // System.out.println(students.stream().map(Student::getName).collect(joining(", "))); // System.out.println(students.stream().map(Student::getName).collect(joining(", ", "<begin> ", " <end>"))); // System.out.println("------------"); // // Map<Integer, Map<String, List<Student>>> map = students.stream(). // collect(groupingBy(Student::getScore, groupingBy(Student::getName))); // System.out.println(map); // System.out.println("------------"); // // Map<Boolean, List<Student>> map2 = students.stream(). // collect(partitioningBy(student -> student.getScore() > 80)); // System.out.println(map2); // System.out.println("------------"); // // Map<Boolean, Map<Boolean, List<Student>>> map3 = students.stream(). // collect(partitioningBy(student -> student.getScore() > 80, // partitioningBy(student -> student.getScore() > 90))); // System.out.println(map3); // System.out.println("------------"); // // Map<Boolean, Long> map4 = students.stream(). // collect(partitioningBy(student -> student.getScore() > 80, counting())); // System.out.println(map4); // System.out.println("------------"); //// // Map<String, Student> map5 = students.stream(). // collect(groupingBy(Student::getName, // collectingAndThen(minBy(Comparator.comparingInt(Student::getScore)), // Optional::get))); // System.out.println(map5); } }
import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; public class StreamTest2 { public static void main(String[] args) { List<String> list = Arrays.asList("nihao", "hello", "world", "welcome"); // Collections.sort(list, (item1, item2) -> item1.length() - item2.length()); // Collections.sort(list, (item1, item2) -> item2.length() - item1.length()); // Collections.sort(list, Comparator.comparingInt(String::length).reversed()); //// 此處lambda參數的類型推斷無法推斷出item為String類型,需要顯式指定;原因在於這是一個獨立的參數,並不是通過list調用方法來得出的 // Collections.sort(list, Comparator.comparingInt((String item) -> item.length()).reversed()); //// 如下代碼無法編譯通過,因為lambda參數要求參數類型應該是String或是String的父類,而Boolean則不是 // Collections.sort(list, Comparator.comparingInt((Boolean item) -> 1).reversed()); //// Collections的sort就是調用List的sort實現的 // list.sort(Comparator.comparingInt(String::length).reversed()); //// 如下代碼必須要顯式聲明item的類型為String // list.sort(Comparator.comparingInt((String item) -> item.length()).reversed()); // // // Collections.sort(list, Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER)); // // // 為何下面這個thenComparing中的參數類型可以推斷出來? // Collections.sort(list, Comparator.comparingInt(String::length). // thenComparing((item1, item2) -> item1.toLowerCase().compareTo(item2.toLowerCase()))); // Collections.sort(list, Comparator.comparingInt(String::length). // thenComparing(Comparator.comparing(String::toLowerCase))); // Collections.sort(list, Comparator.comparingInt(String::length). // thenComparing(Comparator.comparing(String::toLowerCase, Comparator.reverseOrder()))); //// // // welcome, world, nihao, hello // Collections.sort(list, Comparator.comparingInt(String::length).reversed(). // thenComparing(Comparator.comparing(String::toLowerCase, Comparator.reverseOrder()))); // // // welcome, world, nihao, hello, 注意:thenComparing都是根據前一個compare的結果來決定此次是否進行再次排序, // // 如果前一次排序不返回0,那么此次排序結果就直接返回之前的排序結果 Collections.sort(list, Comparator.comparingInt(String::length).reversed(). thenComparing(Comparator.comparing(String::toLowerCase, Comparator.reverseOrder())). thenComparing(Comparator.reverseOrder())); System.out.println(list); } }
public class Student { private String name; private int score; public Student(String name, int score) { this.name = name; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getScore() { return score; } public void setScore(int score) { this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } }