栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Stream操作时Collectors工具类中常用方法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Stream操作时Collectors工具类中常用方法

文章目录
    • 示例文件准备
      • 实体类User :
      • 测试main方法制作数据 :
    • 聚合与分组
      • toList、toSet、toCollection
      • toMap、toConcurrentMap
      • groupingBy、groupingByConcurrent
      • partitioningBy
    • 数据连接
      • joining
    • 操作链
      • collectingAndThen
    • 先操作后聚合
      • mapping
    • 先聚合后操作
      • reducing
    • 数据统计
      • counting
      • averagingDouble、averagingInt、averagingLong
      • summingDouble、summingInt、summingLong
      • maxBy、minBy
      • summarizingDouble、summarizingInt、summarizingLong

示例文件准备 实体类User :
@Data
public class User {
    private String userId;
    private String name;
    private String address;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
    private Date createTime;
    private int age;
    private Long uuid;

}

测试main方法制作数据 :
public static void main(String[] args) throws Exception{
        SimpleDateFormat sdf  = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));

        User user1 = new User();
        user1.setUserId("11");
        user1.setAddress("地址11");
        user1.setName("姓名11");
        user1.setCreateTime(sdf.parse("2020-07-09 21:12:45"));
        user1.setAge(20);

        User user2 = new User();
        user2.setUserId("22");
        user2.setAddress("地址22");
        user2.setName("姓名22");
        user2.setCreateTime(sdf.parse("2020-08-09 21:12:45"));
        user2.setAge(21);

        User user3 = new User();
        user3.setUserId("33");
        user3.setAddress("地址33");
        user3.setName("姓名33");
        user3.setCreateTime(sdf.parse("2020-07-10 21:12:45"));
        user3.setAge(30);

        User user4 = new User();
        user4.setUserId("44");
        user4.setAddress("地址44");
        user4.setName("姓名44");
        user4.setAge(20);

        User user5 = new User();
        user5.setUserId("55");
        user5.setAddress("地址55");
        user5.setName("姓名55");
        user5.setAge(40);

        User user6 = new User();
        user6.setUserId("66");
        user6.setAddress("地址66");
        user6.setName("姓名11");
        user6.setCreateTime(sdf.parse("2016-01-10 21:12:45"));
        user6.setAge(10);

        User user7 = new User();
        user7.setUserId("11");
        user7.setAddress("地址77777");
        user7.setName("姓名11");
        //  user7.setCreateTime(sdf.parse("2020-01-10 21:12:45"));
        user7.setAge(26);

        User user8 = new User();
        user8.setUserId("11");
        user8.setAddress("地址8888");
        user8.setName("姓名11");
        // user8.setCreateTime(sdf.parse("2020-05-10 21:12:45"));

        List list1 = new ArrayList<>();
        list1.add(user1);
        list1.add(user2);
        list1.add(user3);
        list1.add(user4);
        list1.add(user6);
        list1.add(user7);
        list1.add(user8);
}
聚合与分组 toList、toSet、toCollection

描述:将聚合之后的元素,重新封装到队列中,然后返回
返回类型:List和Set和Collection

//输出结果  [姓名11, 姓名22, 姓名33, 姓名44, 姓名11, 姓名11, 姓名11]
List aa = list1.stream().map(User::getName).collect(Collectors.toList());
//输出结果  [姓名11, 姓名22, 姓名33, 姓名44]
Set aa1 = list1.stream().map(User::getName).collect(Collectors.toSet());
//输出结果  [姓名11, 姓名22, 姓名33, 姓名44]
Collection aa2 = list1.stream().map(User::getName).collect(Collectors.toCollection(TreeSet::new));

toMap、toConcurrentMap

描述:这两个方法的作用是将聚合元素,重新组装为Map结构,也就是 k-v 结构。两者用法一样,区别是toMap返回的是Map,toConcurrentMap返回ConcurrentMap,也就是说,toConcurrentMap返回的是线程安全的 Map 结构【toMap结果是 1:1 的 k-v 结构】

返回类型:Map

//输出结果  {66=User(userId=66, name=姓名11, address=地址66, createTime=Sun Jan 10 21:12:45 CST 2016, age=10, uuid=null)XXXXXX数据太多了}
//得到根据id分组后数据
Map map2 = list1.stream()
                .collect(Collectors.toMap(User::getUserId, Function.identity(), (x, y) -> x));

//输出结果  {66=姓名11, 44=姓名44, 33=姓名33, 22=姓名22, 11=姓名11}
//得到根据id分组后的姓名
Map map3 = list1.stream()
                .collect(Collectors.toMap(User::getUserId, User::getName, (x, y) -> x));
groupingBy、groupingByConcurrent

描述:groupingBy与toMap都是将聚合元素进行分组,区别是,toMap结果是 1:1 的 k-v 结构,groupingBy的结果是 1:n 的 k-v 结构。

返回类型:Map>

//输出结果 {0=[User(userId=11, name=姓名11, address=地址8888, createTime=null, age=0, uuid=null)], 20=[User(userId=11, name=姓名11, address=地址11, createTime=Thu Jul 09 21:12:45 CST 2020, age=20, uuid=null), User(userId=44, name=姓名44, address=地址44, createTime=null, age=20, uuid=null)], 21=[User(userId=22, name=姓名22, address=地址22, createTime=Sun Aug 09 21:12:45 CST 2020, age=21, uuid=null)], 26=[User(userId=11, name=姓名11, address=地址77777, createTime=null, age=26, uuid=null)], 10=[User(userId=66, name=姓名11, address=地址66, createTime=Sun Jan 10 21:12:45 CST 2016, age=10, uuid=null)], 30=[User(userId=33, name=姓名33, address=地址33, createTime=Fri Jul 10 21:12:45 CST 2020, age=30, uuid=null)]}
//得到根据age分组后数据
Map> map5 = list1.stream().collect(Collectors.groupingBy(User::getAge));

//输出结果  {0=[User(userId=11, name=姓名11, address=地址8888, createTime=null, age=0, uuid=null)], 20=[User(userId=11, name=姓名11, address=地址11, createTime=Thu Jul 09 21:12:45 CST 2020, age=20, uuid=null), User(userId=44, name=姓名44, address=地址44, createTime=null, age=20, uuid=null)], 21=[User(userId=22, name=姓名22, address=地址22, createTime=Sun Aug 09 21:12:45 CST 2020, age=21, uuid=null)], 26=[User(userId=11, name=姓名11, address=地址77777, createTime=null, age=26, uuid=null)], 10=[User(userId=66, name=姓名11, address=地址66, createTime=Sun Jan 10 21:12:45 CST 2016, age=10, uuid=null)], 30=[User(userId=33, name=姓名33, address=地址33, createTime=Fri Jul 10 21:12:45 CST 2020, age=30, uuid=null)]}
//得到根据age分组后数据
Map> map6 = list1.stream().collect(Collectors.groupingBy(User::getAge, Collectors.toSet()));


既然groupingBy也是分组,是不是也能够实现与toMap类似的功能,比如,根据 id 分组

//输出结果 {66=User(userId=66, name=姓名11, address=地址66, createTime=Sun Jan 10 21:12:45 CST 2016, age=10, uuid=null), 44=User(userId=44, name=姓名44, address=地址44, createTime=null, age=20, uuid=null), 33=User(userId=33, name=姓名33, address=地址33, createTime=Fri Jul 10 21:12:45 CST 2020, age=30, uuid=null), 22=User(userId=22, name=姓名22, address=地址22, createTime=Sun Aug 09 21:12:45 CST 2020, age=21, uuid=null), 11=User(userId=11, name=姓名11, address=地址11, createTime=Thu Jul 09 21:12:45 CST 2020, age=20, uuid=null)}
//与上面的 map2 结果是相同的
 Map map7 = list1.stream()
                .collect(Collectors.groupingBy(User::getUserId, Collectors.collectingAndThen(Collectors.toList(), list -> list.get(0))));

想要线程安全的Map,可以使用groupingByConcurrent

partitioningBy

描述:partitioningBy与groupingBy的区别在于,partitioningBy借助Predicate断言,可以将集合元素分为true和false两部分

返回类型:Map>

//输出结果  {false=[User(userId=66, name=姓名11, address=地址66, createTime=Sun Jan 10 21:12:45 CST 2016, age=10, uuid=null), User(userId=11, name=姓名11, address=地址8888, createTime=null, age=0, uuid=null)], true=[User(userId=11, name=姓名11, address=地址11, createTime=Thu Jul 09 21:12:45 CST 2020, age=20, uuid=null), User(userId=22, name=姓名22, address=地址22, createTime=Sun Aug 09 21:12:45 CST 2020, age=21, uuid=null), User(userId=33, name=姓名33, address=地址33, createTime=Fri Jul 10 21:12:45 CST 2020, age=30, uuid=null), User(userId=44, name=姓名44, address=地址44, createTime=null, age=20, uuid=null), User(userId=11, name=姓名11, address=地址77777, createTime=null, age=26, uuid=null)]}
//按照年龄是否大于11岁 分组
Map> map8 = list1.stream().collect(Collectors.partitioningBy(s -> s.getAge() > 11));
  
//输出结果   {false=[User(userId=11, name=姓名11, address=地址8888, createTime=null, age=0, uuid=null), User(userId=66, name=姓名11, address=地址66, createTime=Sun Jan 10 21:12:45 CST 2016, age=10, uuid=null)], true=[User(userId=11, name=姓名11, address=地址11, createTime=Thu Jul 09 21:12:45 CST 2020, age=20, uuid=null), User(userId=11, name=姓名11, address=地址77777, createTime=null, age=26, uuid=null), User(userId=33, name=姓名33, address=地址33, createTime=Fri Jul 10 21:12:45 CST 2020, age=30, uuid=null), User(userId=22, name=姓名22, address=地址22, createTime=Sun Aug 09 21:12:45 CST 2020, age=21, uuid=null), User(userId=44, name=姓名44, address=地址44, createTime=null, age=20, uuid=null)]}
//按照年龄是否大于11岁 分组
Map> map9 = list1.stream().collect(Collectors.partitioningBy(s -> s.getAge() > 11, Collectors.toSet()));

数据连接 joining

描述:对String类型的元素进行聚合,拼接成一个字符串返回,作用与java.lang.String#join类似,提供了 3 个不同重载方法,可以实现不同的需要

返回类型:String

//输出结果  java张三李四
String q = Stream.of("java", "张三", "李四").collect(Collectors.joining());
        
//输出结果  java, 张三, 李四
String w =Stream.of("java", "张三", "李四").collect(Collectors.joining(", "));

//输出结果  【java, 张三, 李四】
String t =Stream.of("java", "张三", "李四").collect(Collectors.joining(", ", "【", "】"));
操作链 collectingAndThen

描述:它是先对集合进行一次聚合操作,然后通过Function定义的函数,对聚合后的结果再次处理。

返回类型:Map
示例也可以查看这个:collectingAndThen的应用例子

//输出结果  [{"address":"地址44","age":20,"name":"姓名44","userId":"44"},{"address":"地址33","age":30,"createTime":1594386765000,"name":"姓名33","userId":"33"},{"address":"地址22","age":21,"createTime":1596978765000,"name":"姓名22","userId":"22"},{"address":"地址8888","age":0,"name":"姓名11","userId":"11"}]
//取出name相同的人中年龄最小的一个人
Map collect = list1.stream().collect(
                Collectors.groupingBy(User::getName,
                        Collectors.collectingAndThen(Collectors.reducing((c1, c2) -> c1.getAge()< c1.getAge() ? c1 : c2),
                                Optional::get)));
        List list6  = new ArrayList<>(collect.values());
先操作后聚合 mapping

描述:mapping先通过Function函数处理数据,然后通过Collector方法聚合元素

返回类型:T

//输出结果 [姓名11, 姓名22, 姓名33, 姓名44, 姓名11, 姓名11, 姓名11]
//获取name列表
List list8= list1.stream()
                .collect(Collectors.mapping(User::getName, Collectors.toList()));
        System.out.println(list8);
先聚合后操作 reducing

描述: reducing提供了 3 个重载方法:
示例也可以查看这个:reducing的使用例子

//:直接通过BinaryOperator操作,返回值是Optional
public static  Collector> reducing(BinaryOperator op)

//:预定默认值,然后通过BinaryOperator操作
public static  Collector reducing(T identity, BinaryOperator op)

//:预定默认值,通过Function操作元素,然后通过BinaryOperator操作
public static  Collector reducing(U identity, Function mapper, BinaryOperator op)
 //输出结果 Optional[127]
 //计算用户的age总和
 Optional te = list1.stream()
                .map(User::getAge)
                .collect(Collectors.reducing(Integer::sum));
数据统计 counting

描述:统计元素列表的数量
返回类型:Long

Long a = list1.stream().collect(Collectors.counting());
averagingDouble、averagingInt、averagingLong

描述:统计元素列表的平均值
返回类型:3种方法都是Double

Double b = list1.stream().collect(Collectors.averagingInt(User::getAge));
summingDouble、summingInt、summingLong

描述:统计元素列表的和
返回类型:summingDouble返回的是Double类型、summingInt返回的是Integer类型,summingLong返回的是Long类型。

//输出结果  127
int c = list1.stream().collect(Collectors.summingInt(User::getAge));
maxBy、minBy

描述:统计元素列表的最大值/最小值
返回类型:Optional

Optional d = list1.stream().collect(Collectors.minBy(Comparator.comparing(User::getAge)));

Optional e = list1.stream().collect(Collectors.maxBy(Comparator.comparing(User::getAge)));
summarizingDouble、summarizingInt、summarizingLong

描述:统计元素列表的和
返回类型:summarizingDouble返回DoubleSummaryStatistics类型,summarizingInt返回IntSummaryStatistics类型,summarizingLong返回LongSummaryStatistics类型。

//输出结果  IntSummaryStatistics{count=7, sum=127, min=0, average=18.142857, max=30}
IntSummaryStatistics f = list1.stream().collect(Collectors.summarizingInt(User::getAge));
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821393.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号