首页 > 编程语言 >Java8中比较器和收集器的常用示例-排序、流转集合、分组、分区、查找最大最小值

Java8中比较器和收集器的常用示例-排序、流转集合、分组、分区、查找最大最小值

时间:2023-01-05 11:25:24浏览次数:66  
标签:Map stream Collectors 收集器 示例 collect User new Java8

场景

Java8新特性-Stream对集合进行操作的常用API:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/126070657

前面讲Stream的常用api。下面讲比较器和收集器的常用示例。

Java 8 为 java.util.Comparator 接口新增了多种静态和默认方法,使排序操作变得更为简单。

现在,只需通过一系列库调用,就能根据一个属性对 POJO 集合进行排序。

Java 8 还引入了一个新的工具类java.util.stream.Collectors,它提供将流转换回各类集合所需的静态方法。

此外,收集器也可以在“下游”使用,利用它们对分组(grouping)或分区(partitioning)操作进行后期处理

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

实现

利用比较器实现排序

根据字典顺序(自然顺序)对字符串集合排序

 

       List<String> sampleStrings = Arrays.asList("a","d","eee","fff","b");

        List<String> collect = sampleStrings
                .stream()
                .sorted()
                .collect(Collectors.toList());

        System.out.println(collect);//[a, b, d, eee, fff]

根据长度对字符串集合进行排序

        List<String> sampleStrings1 = Arrays.asList("a","dd","eee","fffg","bgggg");
        List<String> collect1 = sampleStrings1
                .stream()
                .sorted(Comparator.comparingInt(String::length))
                .collect(Collectors.toList());

        System.out.println(collect1);//[a, dd, eee, fffg, bgggg]

根据长度和字母顺序对字符串集合进行排序,如果长度相同则按照字母顺序排序

        List<String> stringList = Arrays.asList("a","ddd","bb","cc");
        List<String> collect2 = stringList
                .stream()
                .sorted(Comparator.comparingInt(String::length).thenComparing(Comparator.naturalOrder()))
                .collect(Collectors.toList());

        System.out.println(collect2);//[a, bb, cc, ddd]

将流转换为集合

转换为list

        List<String> collect = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu", "zhouqi")
                .collect(Collectors.toList());

转换为LinkedList

       LinkedList<String> collect2 = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu", "zhouqi", "lisi")
                .collect(Collectors.toCollection(LinkedList::new));

转换为set

        Set<String> collect1 = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu", "zhouqi","lisi")
                .collect(Collectors.toSet());
        System.out.println(collect1);//[lisi, zhouqi, zhaoliu, zhangsan, wangwu]

转换为Array

        String[] strings = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu", "zhouqi")
                .toArray(String[]::new);

转换为Map

        List<User> userList = new ArrayList<>();
        userList.add(new User("霸道",30));
        userList.add(new User("的",40));
        userList.add(new User("程序猿",50));
        userList.add(new User("张三",60));
        userList.add(new User("李四",70));

        Map<Integer, String> collect3 = userList.stream()
                .collect(Collectors.toMap(User::getAge, User::getName));
        System.out.println(collect3);//{50=程序猿, 70=李四, 40=的, 60=张三, 30=霸道}

转换为Map,键为对象属性,值为对象本身

方式一

        Map<Integer, User> collect4 = userList1.stream()
                .collect(Collectors.toMap(User::getId, b -> b));
        System.out.println(collect4);

方式二

        Map<Integer, User> collect5 = userList1.stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));
        System.out.println(collect5);

对Map排序与分组

根据键或值对Map排序

Stream<String> names = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu", "zhouqi", "a", "a", "aa", "bbb", "ccc");
Map<Integer, List<String>> collect1 = names.collect(Collectors.groupingBy(String::length));
System.out.println(collect1);//{1=[a, a], 2=[aa], 3=[bbb, ccc], 4=[lisi], 6=[wangwu, zhouqi], 7=[zhaoliu], 8=[zhangsan]}

Collectors.groupingBy 方法传入 Function 作为第一个参数,表示分类器(classifier)。

在本例中,分类器是每个字符串的长度。如果 groupingBy 方法只传入一个参数,则结果为 Map,

其中键为分类器的值,值为匹配分类器的元素列表。

双参数形式的groupingBy方法传入另一个Collector,它称为下游收集器,用于对名字列表进行后期处理,这种情况下返回的是Map<Integer, Long>

Map<Integer, Long> collect = names1.collect(Collectors.groupingBy(String::length, Collectors.counting()));
System.out.println(collect);//{1=2, 2=1, 3=2, 4=1, 6=2, 7=1, 8=1}

上面按照名字长度的升序输出,如果希望按照降序,可以使用Map.Entry接口的comparingByKey方法

        Stream<String> names2 = Stream.of("zhangsan", "lisi", "wangwu", "zhaoliu", "zhouqi", "a", "a", "aa", "bbb", "ccc");
        Map<Integer, Long> collect2 = names2.collect(Collectors.groupingBy(String::length, Collectors.counting()));
        collect2
                .entrySet()
                .stream()
                .sorted(Map.Entry.comparingByKey(Comparator.reverseOrder()))
                .forEach(e -> System.out.println(e.getKey() +" "+ e.getValue()));

comparingByKey 方法返回一个根据键进行排序的比较器。如果希望以键的相反顺序排序,

可以使用comparingByKey方法的重载形式,它传入比较器作为参数。

Stream.sorted 方法生成一个新的排序流,它不对源数据进行修改。换言之,原始 Map 不受影响。

分区

用户希望将元素集合分成若干个类别

假设存在一个字符串集合,可以通过partitioningBy方法将这些字符串按照偶数长度和奇数长度进行划分

        List<String> stringList = Arrays.asList("a", "bbb", "cc", "ddddd", "eeee");
        Map<Boolean, List<String>> collect = stringList.stream()
                .collect(Collectors.partitioningBy(s -> s.length() % 2 == 0));
        collect.forEach((key,value) -> System.out.printf("%5s: %s%n",key,value));

Collectors.partitioningBy 方法将元素拆分为满足Predicate 与不满足 Predicate 的两类。

输出结果:

        //false: [a, bbb, ddddd]
        // true: [cc, eeee]

如果对每个类别包含多少元素更感兴趣,可以使用partitioningBy方法的重载方法(第二个参数为Collector类型)

        List<String> stringList1 = Arrays.asList("a", "bbb", "cc", "ddddd", "eeee");
        Map<Boolean, Long> collect1 = stringList1.stream()
                .collect(Collectors.partitioningBy(s -> s.length() % 2 == 0, Collectors.counting()));
        collect1.forEach((k,v)->System.out.printf("%5s: %d%n",k,v));

输出结果:

        //false: 3
        // true: 2

查找最大值和最小值

用户希望确定流中的最大值或最小值

方法一:使用 BinaryOperator 接口定义的 maxBy 和 minBy 方法

        List<User> userList1 = new ArrayList<>();
        userList1.add(new User(1,"霸道",30));
        userList1.add(new User(2,"的",40));
        userList1.add(new User(3,"程序猿",50));
        userList1.add(new User(4,"张三",60));
        userList1.add(new User(5,"李四",70));

        //默认用户-流为空时的默认值
        User defaultUser = new User(0,"默认名字",0);
       
        //实现方式1
        //BinaryOperator 是 java.util.function 包定义的一种函数式接口,它继承自 BiFunction 接口,适合在函数和返回值的参数属于同一个类时使用。
        Optional<User> reduce = userList1.stream()
                .reduce(BinaryOperator.maxBy(Comparator.comparingInt(User::getAge)));
        System.out.println("年龄最大的为:"+reduce.orElse(defaultUser).getName());

方法二:使用 Stream 接口定义的 max 和 min 方法

        Optional<User> max = userList1.stream()
                .max(Comparator.comparingInt(User::getAge));

如果直接获取年龄值

        OptionalInt max1 = userList1.stream()
                .mapToInt(User::getAge)
                .max();

方法三:使用 Collectors 类定义的 maxBy 和 minBy 方法。

        Optional<User> collect = userList1.stream()
                .collect(Collectors.maxBy(Comparator.comparingInt(User::getAge)));

 

标签:Map,stream,Collectors,收集器,示例,collect,User,new,Java8
From: https://www.cnblogs.com/badaoliumangqizhi/p/17026986.html

相关文章

  • 华为外包机试题 答案示例
    算法在广不在精,随遇而安,快乐常在1.反转链表  https://www.cnblogs.com/sundayvc/p/16598319.html2.C++——链表内指定区间反转 https://blog.csdn.net/ldm_666/articl......
  • Java8新特性-Lambda表达式
    Lambda表达式在Java语言中引入了一个操作符**“->”**,该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:左侧:指定了Lambda表达式需要的所有参数......
  • Okhttp常用方法示例
    这是我用到的一个util类1publicclassHttpBaseService{23privateOkHttpClientclient=newOkHttpClient();4privatestaticfinalMediaTypeJ......
  • Curator 使用示例
    一、Curator简介ApacheCurator是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API简化了ZooKeeper的操作。通过查看官方文档,可以发现Curator主要解决......
  • NFC 读取卡信息(流程示例2),以公交卡为例
    公交卡的结构1.SELECT选择MF(可不选)可以不选默认也会被选中,但是可以通过这个指令获得文件控制信息FCI发送00A40000023F00接收6f12840e315055422e5359......
  • java8中常用函数式接口Supplier<T>、Consumer<T>、Function<T,R>、Predicate<T>使用示
    场景函数式接口(FunctionalInterface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。而java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用......
  • dremio 数据存储结构示例
    从dremio运行系统摘录一些存储结构,方便了解dremio分布式存储(主要以对象存储为主,当然nas也是可以使用的)部分,整体结构类似,但是文件夹名称可能会不要一样(反射内部的存储结......
  • 第十章《日期与时间》第3节:Java8新日期时间系统简介
    ​Date和Calender都是早期Java项目中用于处理日期和时间的工具类,这两个类在设计上有一些明显的缺陷,这些缺陷主要包括:用于计算日期时间的方法较少、线程不安全、对象中的月份......
  • Java8之Optional中orElse和orElseGet的区别
    背景JAVA8之后引入了optional关于optional的使用也比较多了,此处暂时不表这儿暂且只说一下orElse和orElseGet的区别写了一个获取枚举类型的工具类,来做个例子嗯,怎么......
  • Linux 或 Windows 安装 Kafka,示例实现生产与消费消息(一)
    下载:wgethttps://downloads.apache.org/kafka/3.3.1/kafka_2.12-3.3.1.tgz  注意:kafka正常运行,必须配置zookeeper,kafka安装包已经包括zookeeper服务解压:tar-zxvf k......