Java Stream map, Collectors(toMap, toList, toSet, groupingBy, collectingAndThen)使用案例

 更新时间:2023年09月13日 11:15:05   作者:极光雨雨  
这篇文章主要介绍了Java Stream map, Collectors(toMap, toList, toSet, groupingBy, collectingAndThen)使用案例,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

.map 以及 toList 方法联合使用案例

/**
     * .map  .collect(Collectors.toList)
     */
    private static void method2(){
        List<MyPerson> collect = Stream.of("1:name1", "2:name2").map(new Function<String, MyPerson>() {
            @Override
            public MyPerson apply(String s) {
                String[] split = s.split(":");
                MyPerson myPerson = new MyPerson(Integer.valueOf(split[0]), split[1]);
                return myPerson;
            }
        }).collect(Collectors.toList());
        System.out.println(collect.toString());
    }

实际输出

这里我重写了MyPerson 类的toString 等方法

[MyPerson{id=1, name='name1'}, MyPerson{id=2, name='name2'}]

Stream.of(“1:name1”, “2:name2”) 译为将多个of 中的元素转为Stream 中的集合元素

.map 这里作用为将 Function中的第一个泛型元素也就是Stream 中的元素泛型,转为 MyPerson 对象,这里 MyPerson 为我自己定义的对象,只有id 和 name 两个属性。 重写的方法 apply 为对每个Stream 中的String 元素的操作,并且通过这个方法将返回预期的 MyPerson 对象,即 .map 作用为将Stream 中的每一个元素转为另一种元素的映射操作,实际就是一个转换的中间方法。

.collect 说明接下来要使用集合类操作 即使用了 Collectors.toList() 方法,该方法最终会将Stream 中的元素输出为 List 类型的对象

上一案例 Collectors toMap使用

/**
     * .map   .collect(Collectors.toMap())
     */
    private static void method3(){
        Map<Integer, MyPerson> collect = Stream.of("1:name1", "2:name2").map(new Function<String, MyPerson>() {
            @Override
            public MyPerson apply(String s) {
                String[] split = s.split(":");
                MyPerson myPerson = new MyPerson(Integer.valueOf(split[0]), split[1]);
                return myPerson;
            }
        }).collect(Collectors.toMap(MyPerson::getId, Function.identity()));
        System.out.println(collect.toString());
        MyPerson myPerson = collect.get(1);
        System.out.println(myPerson);
        MyPerson myPerson1 = collect.get(2);
        System.out.println(myPerson1.toString());
    }

实际输出

{1=MyPerson{id=1, name='name1'}, 2=MyPerson{id=2, name='name2'}}
MyPerson{id=1, name='name1'}
MyPerson{id=2, name='name2'}

即 .collect(Collectors.toMap(MyPerson::getId, Function.identity()));

意义为使用集合方法中的toMap() 方法,toMap中,第一个参数为作为Map 的key, Function.identity() 对应key 的值为 当前元素自己,结果如上展示

上述案例也可以写为:map 中 可以直接使用lambda 表达式给出返回结果 s 即Stream 中的每个元素

    /**
     * .map   .collect(Collectors.toMap()) lambda
     */
    private static void method4(){
        Map<Integer, MyPerson> collect = Stream.of("1:name1", "2:name2").map(s -> {
            String[] split = s.split(":");
            MyPerson myPerson = new MyPerson(Integer.valueOf(split[0]), split[1]);
            return myPerson;
        }).collect(Collectors.toMap(MyPerson::getId, Function.identity()));
        System.out.println(collect.toString());
        MyPerson myPerson = collect.get(1);
        System.out.println(myPerson);
        MyPerson myPerson1 = collect.get(2);
        System.out.println(myPerson1.toString());
    }

上述案例

可以进一步简写为:即 .map 中可以直接使用引用某一已经存在的方法来获取结果 MyPerson::transEntity 见末尾MyPerson 中定义的方法

/**
     * .map   .collect(Collectors.toMap()) lambda level up MapTrans
     */
    private static void method5(){
        Map<Integer, MyPerson> collect = Stream.of("1:name1", "2:name2").map(MyPerson::transEntity)
                .collect(Collectors.toMap(MyPerson::getId, Function.identity()));
        System.out.println(collect.toString());
        MyPerson myPerson = collect.get(1);
        System.out.println(myPerson);
        MyPerson myPerson1 = collect.get(2);
        System.out.println(myPerson1.toString());
    }

其中 Function.identity() 也可以如下写法 s -> s 也表示直接获取当前对象作为 Map的值

    /**
     * .map   .collect(Collectors.toMap()) lambda level up MapTrans
     */
    private static void method6(){
        Map<Integer, MyPerson> collect = Stream.of("1:name1", "2:name2").map(MyPerson::transEntity)
                .collect(Collectors.toMap(MyPerson::getId, s -> s));
        System.out.println(collect.toString());
        MyPerson myPerson = collect.get(1);
        System.out.println(myPerson);
        MyPerson myPerson1 = collect.get(2);
        System.out.println(myPerson1.toString());
    }

toList 使用案例

    private static void lambdaTestToList(){
        String m = "a,b,c,d,d,d,d,d";
        Stream.of("a", "aa", "aaa", "b", "bb", "bbb").collect(Collectors.toList()).forEach((item) -> {
            System.out.println(item);
        });
        System.out.println("*******************");
        Stream.of(m.split(",")).collect(Collectors.toList()).forEach((item) -> {
            System.out.println(item);
        });
        System.out.println("*******************");
        MyPerson myPerson = new MyPerson(1, "545");
        MyPerson myPerson1 = new MyPerson(2, "333");
        MyPerson myPerson2 = new MyPerson(3, "445");
        List<MyPerson> list = new ArrayList<>();
        list.add(myPerson);
        list.add(myPerson2);
        list.add(myPerson1);
        List<List<MyPerson>> collect = Stream.of(list).collect(Collectors.toList());
        List<Object> collect1 = Stream.of(list.toArray()).collect(Collectors.toList());
        System.out.println("*******************");
        collect.stream().forEach(item -> {
            System.out.println(item.toString());
        });
        System.out.println("*******************");
        collect1.stream().forEach(item -> {
            System.out.println(item);
        });
    }

输出结果:

a
aa
aaa
b
bb
bbb
*******************
a
b
c
d
d
d
d
d
*******************
*******************
[MyPerson{id=1, name='545'}, MyPerson{id=3, name='445'}, MyPerson{id=2, name='333'}]
*******************
MyPerson{id=1, name='545'}
MyPerson{id=3, name='445'}
MyPerson{id=2, name='333'}

Process finished with exit code 0

可以看的出常见的 逗号拼接方式的字符串也可以通过 toList 快速转为我们常用的 list 形式并做一定的操作

toSet

上述案例中直接list 转 set 做去重和类型转换十分快捷

    // 定义
    private static String arrayStr = "1,2,3,4, 5,6,7";
    private static String arrayStrEN = "a,b,c,d,d,d,f";
    private static List<MyPerson> listObject = new ArrayList<>();
    private static List<JSONObject> listJsonObject = new ArrayList<>();
    static {
        MyPerson myPerson = new MyPerson(1, "545");
        MyPerson myPerson1 = new MyPerson(2, "333");
        MyPerson myPerson2 = new MyPerson(3, "445");
        MyPerson myPerson3 = new MyPerson(2, "333");
        listObject.add(myPerson);
        listObject.add(myPerson1);
        listObject.add(myPerson2);
        listObject.add(myPerson3);
        JSONObject object = new JSONObject();
        object.put("dep", 124);
        object.put("userId", "14");
        object.put("names", "aka");
        JSONObject object1 = new JSONObject();
        object1.put("dep", 124);
        object1.put("userId", "14");
        object1.put("names", "aka1");
        JSONObject object2 = new JSONObject();
        object2.put("dep", 125);
        object2.put("userId", "15");
        object2.put("names", "aka2");
        JSONObject object3 = new JSONObject();
        object3.put("dep", 125);
        object3.put("userId", "15");
        object3.put("names", "aka3");
        JSONObject object4 = new JSONObject();
        object4.put("dep", 136);
        object4.put("userId", "14");
        object4.put("names", "aka4");
        listJsonObject.add(object);
        listJsonObject.add(object1);
        listJsonObject.add(object2);
        listJsonObject.add(object3);
        listJsonObject.add(object4);
    }
    public static void lambdaToSet(){
        Stream.of(arrayStr.split(",")).collect(Collectors.toSet()).forEach(item -> {
            System.out.println(item.trim());
        });
        System.out.println("---------------");
        Stream.of(arrayStrEN.split(",")).collect(Collectors.toSet()).forEach(item -> {
            System.out.println(item.trim());
        });
        System.out.println("-----------");
        Stream.of(listObject.toArray()).collect(Collectors.toSet()).forEach(item -> {
            System.out.println(item);
        });
    }

输出结果:

1
2
3
4
5
6
7
---------------
a
b
c
d
f
-----------
MyPerson{id=2, name='333'}
MyPerson{id=3, name='445'}
MyPerson{id=1, name='545'}

groupingBy collectingAndThen 使用

// 定义
private static List<MyPerson> listObject = new ArrayList<>();
    private static List<JSONObject> listJsonObject = new ArrayList<>();
    static {
        MyPerson myPerson = new MyPerson(1, "545");
        MyPerson myPerson1 = new MyPerson(2, "333");
        MyPerson myPerson2 = new MyPerson(3, "445");
        MyPerson myPerson3 = new MyPerson(2, "333");
        listObject.add(myPerson);
        listObject.add(myPerson1);
        listObject.add(myPerson2);
        listObject.add(myPerson3);
        JSONObject object = new JSONObject();
        object.put("dep", 124);
        object.put("userId", "14");
        object.put("names", "aka");
        JSONObject object1 = new JSONObject();
        object1.put("dep", 124);
        object1.put("userId", "14");
        object1.put("names", "aka1");
        JSONObject object2 = new JSONObject();
        object2.put("dep", 125);
        object2.put("userId", "15");
        object2.put("names", "aka2");
        JSONObject object3 = new JSONObject();
        object3.put("dep", 125);
        object3.put("userId", "15");
        object3.put("names", "aka3");
        JSONObject object4 = new JSONObject();
        object4.put("dep", 136);
        object4.put("userId", "14");
        object4.put("names", "aka4");
        listJsonObject.add(object);
        listJsonObject.add(object1);
        listJsonObject.add(object2);
        listJsonObject.add(object3);
        listJsonObject.add(object4);
    }
public static void lambdaGroupBy(){
        System.out.println("--------------按某一属性分组 返回key Object 的Map");
        Map<Integer, List<MyPerson>> collect = listObject.stream().collect(Collectors.groupingBy(MyPerson::getId));
        System.out.println(collect.toString());
        System.out.println("--------------按某些属性的组合作为键 返回key Object的Map");
        Map<String, List<MyPerson>> collect1 = listObject.stream().collect(Collectors.groupingBy(myPerson -> myPerson.getId() + myPerson.getName() + ""));
        System.out.println(collect1.toString());
        System.out.println("--------------按JSON 的某些属性组合作为键  返回key Object的Map");
        Map<String, List<JSONObject>> collect2 = listJsonObject.stream().collect(Collectors.groupingBy(item -> item.get("dep") + item.getString("userId")));
        System.out.println(collect2);
        System.out.println("--------------按某一属性分组后, 获取当前分组后Map的size 可用于统计");
        Integer collect3 = listObject.stream().collect(Collectors.collectingAndThen(Collectors.groupingBy(MyPerson::getId), Map::size));
        System.out.println(collect3);
    }

main 中运行 lambdaGroupBy

输出结果如下:

--------------按某一属性分组 返回key Object 的Map
{1=[MyPerson{id=1, name='545'}], 2=[MyPerson{id=2, name='333'}, MyPerson{id=2, name='333'}], 3=[MyPerson{id=3, name='445'}]}
--------------按某些属性的组合作为键 返回key Object的Map
{1545=[MyPerson{id=1, name='545'}], 3445=[MyPerson{id=3, name='445'}], 2333=[MyPerson{id=2, name='333'}, MyPerson{id=2, name='333'}]}
--------------按JSON 的某些属性组合作为键  返回key Object的Map
{12515=[{"names":"aka2","userId":"15","dep":125}, {"names":"aka3","userId":"15","dep":125}], 12414=[{"names":"aka","userId":"14","dep":124}, {"names":"aka1","userId":"14","dep":124}], 13614=[{"names":"aka4","userId":"14","dep":136}]}
--------------按某一属性分组后, 获取当前分组后Map的size 可用于统计
3

groupingBy 用意为将每一个元素按照某一种属性或多种属性执行分组操作,返回为map key 为分组的属性条件,值为当前元素

collectingAndThen 即执行集合操作后再执行某一方法

总结

通过 stream 使一般的集合对象成为可以执行Stream 操作的对象map 将每一个元素通过某些操作转化为另一种元素

Collectors

toMap 将每一种元素转为Map类型的结构,可以通过键拿到对应的元素,这里相当于是 数据库中通过id 获取某一条记录的数据一样,相当于自己建立了一个数据索引,对于数据暂存和优化以及操作十分方便,而且可以省去繁琐的简单操作将数据转为这一数据结构的过程,而且符合获取数据时的习惯。

toList 快速将多个元素转为List 而不用自己执行遍历操作

toSet 快速将多个元素转为set集合 可以用于去重操作

groupingBy 通过该方法可以快速对数据分组,同样省去了自己封装简单代码的过程

collectingAndThen 集合类操作和其他结果的聚合操作,同时是为了提升效率

虽然一般情况下不需要考虑代码的速度问题,但这里还是说一下Stream 的使用场景经过对比,其实最简单的循环迭代方式对于较少和较简单的数据来说 for 等基本操作反而花费的时间是要比 Stream 快的。

这里我理解 Stream 是使用时间换来了代码的优化和简洁,但是对于不常使用Stream的人来说易读性并不太友好。

Stream 使用场景如下

  • 在循环迭代次数较少的情况下,常规的迭代方式性能反而更好
  • 在单核CPU服务器配置环境中,常规迭代方式更有优势
  • 在大数据循环迭代中,如果服务器是多核CPU的情况,采用Stream的并行迭代优势明显

MyPerson对象定义

equals hashCode 为了对象比较一定需要重写 直接使用代码生成的即可

import java.util.Objects;
public class MyPerson {
    private int id;
    private String name;
    public MyPerson() {
    }
    public MyPerson(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "MyPerson{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MyPerson myPerson = (MyPerson) o;
        return id == myPerson.id &&
                Objects.equals(name, myPerson.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
    public static MyPerson transEntity(String s){
        String[] split = s.split(":");
        MyPerson myPerson = new MyPerson(Integer.valueOf(split[0]), split[1]);
        return myPerson;
    }
}

到此这篇关于Java Stream map, Collectors(toMap, toList, toSet, groupingBy, collectingAndThen)使用案例的文章就介绍到这了,更多相关Java Stream map, Collectors内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于JSCH使用自定义连接池的说明

    关于JSCH使用自定义连接池的说明

    这篇文章主要介绍了关于JSCH使用自定义连接池的说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • 在Java中使用日志框架log4j的方法

    在Java中使用日志框架log4j的方法

    Log4j有三个主要的组件/对象:Loggers(记录器),Appenders (输出源)和Layouts(布局)。这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出,今天通过本文给大家分享Java日志框架log4j的相关知识,感兴趣的朋友一起看看吧
    2021-08-08
  • MyBatis自定义SQL拦截器示例详解

    MyBatis自定义SQL拦截器示例详解

    Mybatis支持对Executor、StatementHandler、PameterHandler和ResultSetHandler 接口进行拦截,也就是说会对这4种对象进行代理,下面这篇文章主要给大家介绍了关于MyBatis自定义SQL拦截器的相关资料,需要的朋友可以参考下
    2021-10-10
  • Java使用Cipher类实现加密的过程详解

    Java使用Cipher类实现加密的过程详解

    这篇文章主要介绍了Java使用Cipher类实现加密的过程详解,Cipher类提供了加密和解密的功能,创建密匙主要使用SecretKeySpec、KeyGenerator和KeyPairGenerator三个类来创建密匙。感兴趣可以了解一下
    2020-07-07
  • Java输入数据的知识点整理

    Java输入数据的知识点整理

    在本篇文章里小编给大家整理的是关于Java如何输入数据的相关知识点内容,有兴趣的朋友们学习参考下。
    2020-01-01
  • Spring AOP之@Around,@AfterReturning使用、切不进去的解决方案

    Spring AOP之@Around,@AfterReturning使用、切不进去的解决方案

    这篇文章主要介绍了Spring AOP之@Around,@AfterReturning使用、切不进去的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • 流式图表拒绝增删改查之kafka核心消费逻辑下篇

    流式图表拒绝增删改查之kafka核心消费逻辑下篇

    这篇文章主要为大家介绍了流式图表拒绝增删改查之kafka核心消费逻辑讲解的下篇,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Java中的==使用方法详解

    Java中的==使用方法详解

    这篇文章主要介绍了Java中“==”的使用方法,,==可以使用在基本数据类型变量和引用数据类型变量中,equals()是方法,只能用于引用数据类型,需要的朋友可以参考下
    2022-09-09
  • Java线程生命周期图文详细讲解

    Java线程生命周期图文详细讲解

    在java中,任何对象都要有生命周期,线程也不例外,它也有自己的生命周期。线程的整个生命周期可以分为5个阶段,分别是新建状态、就绪状态、运行状态、阻塞状态和死亡状态
    2023-01-01
  • Java反射获取实例的速度对比分析

    Java反射获取实例的速度对比分析

    这篇文章主要介绍了Java反射获取实例的速度对比分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09

最新评论