2020了你还不会Java8新特性?(五)收集器比较器用法详解及源码剖析 (2)

完成一个功能时有多个方法,使用特化的方法。因为效率会更高。减少了装箱拆箱的操作。减少性能损耗。

举例: 简单功能实现 public static void main(String[] args) { List<String> list = Arrays.asList("nihao", "hello", "world", "welcome"); //对list按照字母的升序排序 // list.stream().sorted().forEach(System.out::println); //按照字符串的长度排序 // Collections.sort(list, (item1, item2) -> item1.length() - item2.length()); // Collections.sort(list, Comparator.comparingInt(String::length)); //字符串的降序排序 // list.sort(Comparator.comparingInt(String::length).reversed()); // 下边的形式会报错 item识别成了(Obejct). //lambda表达式的类型推断. 如果无法推断类型,需要自己制定类型 // list.sort(Comparator.comparingInt(item-> item.length()).reversed()); //这样写就成功了. list.sort(Comparator.comparingInt((String item )-> item.length()).reversed()); //为什么这个地方无法推断类型? // 能推断出的 : list.stream().... Strean<T> 传递的有参数. 精确的类型可以进行类型推断. //这个地方没有明确具体是什么类型.ToIntFunction<? super T> .可以是String 或者在往上的父类 这个地方看成了Object类了. // list.sort(Comparator.comparingInt((Boolean item)-> 1).reversed()); //这种Boolean 就会报错.编译不通过. System.out.println(list); } 比较器深入举例练习 举例:两层的比较.先按照字符串的长度升序排序. 长度相同,根据每一个ASCII码的顺序排序、

thenComparing()多级排序的练习。;

List<String> list = Arrays.asList("nihao", "hello", "world", "welcome"); //两层的比较.先按照字符串的长度升序排序. 长度相同,根据每一个ASCII码的升序排序. (不区分大小写的 ,按照字母排序的规则) 几种实现的方法。 list.sort(Comparator.comparingInt(String::length).thenComparing(String.CASE_INSENSITIVE_ORDER)); list.sort(Comparator.comparingInt(String::length).thenComparing((item1,item2) -> item1.toUpperCase().compareTo(item2.toUpperCase()))); list.sort(Comparator.comparingInt(String::length).thenComparing(Comparator.comparing(String::toUpperCase))); //排序后将顺序翻转过来. reverseOrder(); list.sort(Comparator.comparingInt(String::length).thenComparing(String::toLowerCase,Comparator.reverseOrder())); // 按照字符串的长度降序排序, 再根据ASCII的降序排序 list.sort(Comparator.comparingInt(String::length).reversed() .thenComparing(String::toLowerCase,Comparator.reverseOrder())); //多级排序 list.sort(Comparator.comparingInt(String::length).reversed() .thenComparing(String::toLowerCase, Comparator.reverseOrder()) .thenComparing(Comparator.reverseOrder())); // 最后一个thenComparing()没有发生作用。 自定义一个简单的收集器

jdk提供了Collector接口。

public class MySetCollector<T> implements Collector<T,Set<T>,Set<T>> { @Override public Supplier<Set<T>> supplier() { //用于提供一个空的容器 System.out.println("supplier invoked! "); return HashSet::new; // 不接受对象,返回一个Set对象 } @Override public BiConsumer<Set<T>, T> accumulator() { // 累加器类型. 接收两个参数不返回值. //完成的功能: 不断的往set中添加元素 System.out.println("accumulator invoked! "); return Set<T>::add ; // return HashSet<T>::add ; 返回HashSet报错. 原因: 返回的是中间类型的返回类型. 不论返回什么类型的Set ,Set都符合要求. } @Override public BinaryOperator<Set<T>> combiner() { //将并行流的多个结果给合并起来. System.out.println("combiner invoked! "); return (set1,set2)->{ set1.addAll(set2); return set1; }; } @Override public Function<Set<T>, Set<T>> finisher() { //完成器,把所有的结果都合并在一起. 返回一个最终的结果类型 //如果中间类型 和最终结果类型一致, 不执行此方法; System.out.println("finisher invoked! "); // return t -> t ; return Function.identity(); // 总是返回参数. } @Override public Set<Characteristics> characteristics() { System.out.println("characterstics invoked! "); return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH,Characteristics.UNORDERED)); // 这个地方 不给参数,IDENTITY_FINISH . 则会调用finisher() } public static void main(String[] args) { List<String> list = Arrays.asList("hello", "world"); Set<String> collect = list.stream().collect(new MySetCollector<>()); System.out.println(collect); } 输出结果为: supplier invoked! accumulator invoked! combiner invoked! characterstics invoked! characterstics invoked! [world, hello] }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwyjw.html