JDK Stream流式API使用总结

f496fccf10c82c9ef4ed1a372f1a388f.png

前言

 JDKJava Development Kit英文首字母大写缩写,是 Sun 公司(已被 Oracle 收购)针对 Java 开发员的软件开发工具包。自从 Java 推出以来,JDK 已经成为使用最广泛的 Java SDK。从JDK8版本开始新增了Stream流式API的功能,该功能特性最大的优势就是能够大大降低代码量和提高可读性。

jdk stream filter的使用

filter是stream api用的最多的功能,它主要作用是可以根据多个条件过滤集合元素数据,下面看个示例:

1、先定义一个测试用的POJO类:

// 定义一个测试用的POJO
@Data
public class Student {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

2、测试filter代码:

public class StreamDemo {


    public static void main(String[] args) {
        //测试filter
        testFilter();
    }


    private static void testFilter(){
        List<Student> studentList = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        studentList.add(zhangsan);
        studentList.add(lisi);
        studentList.add(wangwu);
        // 过滤后的集合
        List<Student> filterAgeStudentList = studentList.stream()
        // 过滤年龄小于30岁的
        .filter(student -> student.getAge() < 30)
        // 过滤年龄大于于20岁的
        .filter(student -> student.getAge() > 20)
        // 保存到新的集合
        .collect(Collectors.toList());
        System.out.println(filterAgeStudentList);
    }
}

3、控制台输出截图:

466f43611864740d4c6320562281462f.png

jdk stream toMap的使用

1、toMap主要作用是将集合内元素按某个属性转换为Map,示例代码如下:

public class StreamDemo {


    public static void main(String[] args) {
        testToMap();
    }


    private static void testToMap() {
        List<Student> studentList = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        Student wangwu2 = new Student("wangwu", 50);
        studentList.add(zhangsan);
        studentList.add(lisi);
        studentList.add(wangwu);
        studentList.add(wangwu2);


        Map<String, Student> nameMap = studentList.stream()
                // 1、Collectors.toMap(第一个参数表示key, 第二个参数表示val(固定写法), 第三个参数表示重复key的处理策略(可覆盖,可丢弃))
                // 2、第三个参数可以不写,如果不写第三个策略参数,如果集合元素中存在重复的key,会报错java.lang.IllegalStateException: Duplicate key
                // 3、覆盖策略决定数据去留,如果选择oldKey表示保留先处理的元素,新进来的丢弃,选择newKey则反之
                .collect(Collectors.toMap(Student::getName, Function.identity(), (oldKey, newKey) -> oldKey));


        System.out.println(nameMap);
    }
}

2、控制台输出截图:

1bcecc4695a2df59b75c7ddaf3b74105.png

3、toMap使用注意事项:

1、Collectors.toMap(第一个参数表示key, 第二个参数表示val(固定写法), 第三个参数表示重复key的处理策略(可覆盖,可丢弃));

2、第三个参数可以不写,如果不写第三个策略参数,如果集合元素中存在重复的key,会报错java.lang.IllegalStateException: Duplicate key,建议第三个参数要写;

3、覆盖策略决定数据去留,如果选择oldKey表示保留先处理的元素,新进来的丢弃,选择newKey则反之;

jdk stream groupBy的使用

1、groupBy的主要作用是将集合内元素按照某个属性相同的值进行分组,类似sql的group by语句,示例代码如下:

public class StreamDemo {


    public static void main(String[] args) {
        testGroupBy();
    }
    private static void testGroupBy() {
        List<Student> studentList = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        Student wangwu2 = new Student("wangwu", 50);
        studentList.add(zhangsan);
        studentList.add(lisi);
        studentList.add(wangwu);
        studentList.add(wangwu2);


        Map<String, List<Student>> nameMap = studentList.stream()
                // 按名称相同的分组
                .collect(Collectors.groupingBy(Student::getName));


        System.out.println(nameMap);
    }
}

2、控制台输出截图:

7576541d649b1aea2dddd0bebb58be3f.png

3、注意返回类型是Map<key, List>结构,可以看到两个名称为wangwu的分组到了一个集合中。

jdk stream map和distinct去重的使用

1、map主要作用是从集合对象元素提取对象某个属性,distinct主要作用是对集合元素进行去重,通过map和distinct是搭配使用的,所以放到一块演示,示例代码如下:

public class StreamDemo {


    public static void main(String[] args) {
        testMap();
    }


    private static void testMap() {
        List<Student> studentList = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        Student wangwu2 = new Student("wangwu", 50);
        studentList.add(zhangsan);
        studentList.add(lisi);
        studentList.add(wangwu);
        studentList.add(wangwu2);


        List<String> nameList = studentList.stream()
                //提取名称
                .map(Student::getName)
                //可以加上去重的支持
                .distinct()
                .collect(Collectors.toList());


        System.out.println(nameList);
    }
}

2、控制台输出截图如下:

8846a96d3f3746b91e794be5b3c8a8b9.png

3、可以看到wangwu被成功去重,只保留一个。

jdk stream flatmap的使用

1、flatmap主要作用是将集合元素拉平,例如将List<List>嵌套的二维集合拉平为List一维集合,主要作用是拉平降维,代码示例如下:

public class StreamDemo {


    public static void main(String[] args) {
        testFlatMap();
    }


    private static void testFlatMap() {
        Map<String, List<Student>> studentMap = new HashMap<>();
        Student zhangsan1 = new Student("zhangsan", 20);
        Student zhangsan2 = new Student("zhangsan", 21);
        Student lisi1 = new Student("lisi", 20);
        Student lisi2 = new Student("lisi", 21);
        Student wangwu1 = new Student("wangwu", 20);
        Student wangwu2 = new Student("wangwu", 21);
        //
        List<Student> lisiList = new ArrayList<>();
        List<Student> wangwuList = new ArrayList<>();
        List<Student> zhangsanList = new ArrayList<>();
        //添加到list
        lisiList.add(lisi1);
        lisiList.add(lisi2);
        wangwuList.add(wangwu1);
        wangwuList.add(wangwu2);
        zhangsanList.add(zhangsan1);
        zhangsanList.add(zhangsan2);
        //添加到map
        studentMap.put("zhangsan", zhangsanList);
        studentMap.put("lisi", lisiList);
        studentMap.put("wangwu", wangwuList);


        //二维数组
        Collection<List<Student>> values = studentMap.values();


        //将二维集合转为一维,通过flatMap进行拉平
        List<Student> studentList = values.stream().flatMap(Collection::stream).collect(Collectors.toList());


        System.out.println(studentList);
    }
}

2、控制台输出截图如下:

48ae4caf4df83d3e8a023541343a593b.png

3、很多人会问flatmap跟map的区别,实际上flatmap跟map作用完全不一样,没什么可比较的,如果一定要说个区别那就是:map输入集合和输出集合元素数量是相同的,map不会改变元素数量,flatmap可以改变输入和输出的元素数量;

jdk stream max/min/count/sum等聚合函数的使用

1、聚合函数主要作用就是对某些维度进行统计,代码示例如下:

public class StreamDemo {


    public static void main(String[] args) {
        testAggregation();
    }


    private static void testAggregation() {
        List<Student> studentList = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        Student wangwu2 = new Student("wangwu", 50);
        studentList.add(zhangsan);
        studentList.add(lisi);
        studentList.add(wangwu);
        studentList.add(wangwu2);


        //统计年龄总和
        int totalAge = studentList.stream().mapToInt(Student::getAge).sum();
        //统计名称为wangwu的人数
        long wangwuCount = studentList.stream().filter(ele -> "wangwu".equals(ele.getName())).count();
        //统计年龄最大的学生
        Student ageMaxStudent = studentList.stream().max(Comparator.comparingInt(Student::getAge)).get();
        //统计年龄最小的学生
        Student ageMinStudent = studentList.stream().min(Comparator.comparingInt(Student::getAge)).get();
        //按名称统计不同名称数量
        Map<String, Long> groupByName = studentList.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));


        System.out.println(String.format("totalAge=%s, wangwuCount=%s, ageMaxStudent=%s, ageMinStudent=%s, groupByName=%s",
                totalAge, wangwuCount, ageMaxStudent.getAge(), ageMinStudent.getAge(), groupByName));
    }


}

2、控制台输出截图如下:

c733af2dfbd8779443fb6779a919e023.png

jdk stream allMatch、anyMatch的使用

1、allMatch、anyMatch主要作用是对集合元素进行整体条件判断,是否全部满足条件、或任意一个满足条件,这两个API也是很常用的,示例代码如下:

public class StreamDemo {


    public static void main(String[] args) {
        testMatch();
    }


    private static void testMatch() {
        List<Student> studentList = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        Student wangwu2 = new Student("wangwu", 50);
        studentList.add(zhangsan);
        studentList.add(lisi);
        studentList.add(wangwu);
        studentList.add(wangwu2);


        //校验集合每个元素都匹配
        boolean allMatch = studentList.stream().allMatch(ele -> "zhangsan".equals(ele.getName()));
        //校验集合任意1个元素匹配
        boolean anyMatch = studentList.stream().anyMatch(ele -> "zhangsan".equals(ele.getName()));


        System.out.println(String.format("allMatch=%s, anyMatch=%s", allMatch, anyMatch));
    }
}

2、控制台输出截图如下:

6e428c28be226b1cec216e02586aed47.png

jdk stream concat的使用

1、concat作用主要是将两个集合合并后进行一次性流式处理,示例代码如下:

public class StreamDemo {


    public static void main(String[] args) {
        testConcat();
    }


    private static void testConcat() {


        //集合1
        List<Student> studentList1 = new ArrayList<>();
        Student zhangsan = new Student("zhangsan", 20);
        Student lisi = new Student("lisi", 25);
        Student wangwu = new Student("wangwu", 40);
        Student wangwu2 = new Student("wangwu", 50);
        studentList1.add(zhangsan);
        studentList1.add(lisi);


        //集合2
        List<Student> studentList2 = new ArrayList<>();
        studentList2.add(wangwu);
        studentList2.add(wangwu2);


        //两个集合的流
        Stream<Student> stream1 = studentList1.stream();
        Stream<Student> stream2 = studentList2.stream();


        //将两个集合流合并一起
        Stream<Student> concatStream = Stream.concat(stream1, stream2);


        //合并后遍历
        concatStream.forEach(System.out::println);
    }
}

2、控制台输出截图如下:

b11c1dd6644d1aa12335d84f6a367f5b.png

---------- 正文结束 ----------
长按扫码关注微信公众号

Java软件编程之家
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值