目录

java 8 特性:Stream的使用方法

简单介绍Java的Stream用法

Stream简介

Stream是Java8提供的一个新的API,它位于java.util.stream包下。Stream API提供了一种新的方式来对Java集合进行操作,这种操作方式极大的提高了Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。 我们可以将元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果

Stream方法

  • 示例代码
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Employee {
    private Long empno; //员工号
    private String ename; //员工姓名
    private Integer salary; //薪水
    private Integer deptno; //所属部门号
    //此处省略get/set方法、构造方法以及toString方法
}
Employee e1 = new Employee(7369L, "SMITH", 800, 20);
Employee e2 = new Employee(7499L, "ALLEN", 1600, 30);
Employee e3 = new Employee(7521L, "WARD", 1250, 30);
Employee e4 = new Employee(7782L, "CLARK", 2450, 10);
Employee e5 = new Employee(7876L, "ADAMS", 1100, 20);

List<Employee> employees = Arrays.asList(e1, e2, e3, e4, e5);
  • forEach方法 forEach方法用于迭代stream流中的每一个元素
1
employees.stream().forEach(System.out::println);

执行结果:

1
2
3
4
5
Employee{empno=7369, ename='SMITH', salary=800, deptno=20}
Employee{empno=7499, ename='ALLEN', salary=1600, deptno=30}
Employee{empno=7521, ename='WARD', salary=1250, deptno=30}
Employee{empno=7782, ename='CLARK', salary=2450, deptno=10}
Employee{empno=7876, ename='ADAMS', salary=1100, deptno=20}
  • map方法 map方法用于根据自定义的规则对stream流中的数据做一对一的映射
1
2
3
//获取所有员工的姓名
List<String> enames = employees.stream().map(employee -> employee.getEname()).collect(Collectors.toList());
enames.stream().forEach(System.out::println);

执行结果:

1
2
3
4
5
SMITH
ALLEN
WARD
CLARK
ADAMS
  • mapToInt/mapToLong/mapToDouble方法 这几个方法主要用来对stream流中的元素产生单个的统计结果
1
2
3
 //获取所有员工的薪水总和
int totalSalary = employees.stream().mapToInt(employee -> employee.getSalary()).sum();
System.out.println("薪水总和:" + totalSalary);

执行结果:

1
薪水总和:7200
  • filter方法 filter方法用于根据设置的条件对stream流中的数据做过滤操作
1
2
3
//获取薪水超过1500的员工
List<Employee> filterEmp = employees.stream().filter(employee -> employee.getSalary()>1500).collect(Collectors.toList());
filterEmp.stream().forEach(System.out::println);

执行结果:

1
2
Employee{empno=7499, ename='ALLEN', salary=1600, deptno=30}
Employee{empno=7782, ename='CLARK', salary=2450, deptno=10}
  • sorted方法 sorted方法用于对流中的元素进行排序
1
2
3
//按员工的薪水由低到高排序
List<Employee> sortedEmp = employees.stream().sorted(Comparator.comparing(Employee::getSalary)).collect(Collectors.toList());
sortedEmp.stream().forEach(System.out::println);

执行结果:

1
2
3
4
5
Employee{empno=7369, ename='SMITH', salary=800, deptno=20}
Employee{empno=7876, ename='ADAMS', salary=1100, deptno=20}
Employee{empno=7521, ename='WARD', salary=1250, deptno=30}
Employee{empno=7499, ename='ALLEN', salary=1600, deptno=30}
Employee{empno=7782, ename='CLARK', salary=2450, deptno=10}
  • Collectors类 Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
//按员工所属部门号进行分类
Map<Integer, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(employee -> employee.getDeptno()));
for(Map.Entry<Integer, List<Employee>> entry : map.entrySet()) {
    System.out.println("key: " + entry.getKey() + "  value:" + entry.getValue());
}

System.out.println();

//获取员工姓名,用","进行拼接
String enameString = employees.stream().map(employee -> employee.getEname()).collect(Collectors.joining(","));
System.out.println(enameString);

执行结果:

1
2
3
4
5
key: 20  value:[Employee{empno=7369, ename='SMITH', salary=800, deptno=20}, Employee{empno=7876, ename='ADAMS', salary=1100, deptno=20}]
key: 10  value:[Employee{empno=7782, ename='CLARK', salary=2450, deptno=10}]
key: 30  value:[Employee{empno=7499, ename='ALLEN', salary=1600, deptno=30}, Employee{empno=7521, ename='WARD', salary=1250, deptno=30}]

SMITH,ALLEN,WARD,CLARK,ADAMS
  • 方法串联 Stream API提供的多个方法可以在一行代码中同时串联使用
1
2
3
//获取20号部门员工姓名,按薪水从高到低排序
List<String> names = employees.stream().filter(employee -> employee.getDeptno().equals(20)).sorted(Comparator.comparing(Employee::getSalary).reversed()).map(employee -> employee.getEname()).collect(Collectors.toList());
names.stream().forEach(System.out::println);

执行结果:

1
2
ADAMS
SMITH
    • 总结 Stream API提供了多个方法对集合进行映射、过滤、排序等操作,相比于Java7,大大简化了代码的开发。记住:Stream API中的方法并不会影响原始集合

测试demo

StreamList.java

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
package com.imooc.zhangxiaoxi.stream;

import com.imooc.zhangxiaoxi.lambda.cart.CartService;
import com.imooc.zhangxiaoxi.lambda.cart.Sku;
import lombok.Data;
import org.junit.Before;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

@Data
class Employee {
    private Long empno; //员工号
    private String ename; //员工姓名
    private Integer salary; //薪水
    private Integer deptno; //所属部门号

    public Employee(long l, String adams, int i, int i1) {
        empno = l;
        ename = adams;
        salary = i;
        deptno = i1;
    }
    //此处省略get/set方法、构造方法以及toString方法
}

public class StreamList {
    List<Sku> list;
    List<Employee> employees;

    List<String> labels;

    @Before
    public void init() {
        list = CartService.getCartSkuList();

        Employee e1 = new Employee(7369L, "SMITH", 800, 20);
        Employee e2 = new Employee(7499L, "ALLEN", 1600, 30);
        Employee e3 = new Employee(7521L, "WARD", 1250, 30);
        Employee e4 = new Employee(7782L, "CLARK", 2450, 10);
        Employee e5 = new Employee(7876L, "ADAMS", 1100, 20);
        employees = Arrays.asList(e1, e2, e3, e4, e5);

        String l1 = "iresource.fault.io/acceleratorcard";
        String l2 = "iresource.fault.io/sharestorage";
        String l3 = "iresource.fault.io/calcnetwork";


        labels = Arrays.asList(l1, l2, l3);


    }

    @Test
    public void listTest() {
        employees.forEach(System.out::println);

//        employees.forEach( ele -> {
//            String tmp = ele+"eeee";
//            System.out.println(tmp);
//        });

        //获取所有员工的姓名
        List<String> enames = employees.stream().map(employee -> employee.getEname()).collect(Collectors.toList());
        enames.stream().forEach(System.out::println);

        //获取所有员工的薪水总和

//        int totalSalary = employees.stream().mapToInt(Employee::getSalary).sum();
        int totalSalary = employees.stream().mapToInt(employee -> employee.getSalary()).sum();
        System.out.println("薪水总和:" + totalSalary);

        //获取薪水超过1500的员工
        List<Employee> filterEmp = employees.stream().filter(employee -> employee.getSalary() > 1500).collect(Collectors.toList());
        filterEmp.stream().forEach(System.out::println);

        //按员工的薪水由低到高排序
        List<Employee> sortedEmp = employees.stream().sorted(Comparator.comparing(Employee::getSalary)).collect(Collectors.toList());
        sortedEmp.stream().forEach(System.out::println);

        //按员工所属部门号进行分类
        Map<Integer, List<Employee>> map = employees.stream().collect(Collectors.groupingBy(employee -> employee.getDeptno()));
        for (Map.Entry<Integer, List<Employee>> entry : map.entrySet()) {
            System.out.println("key: " + entry.getKey() + "  value:" + entry.getValue());
        }

        System.out.println();

        //获取员工姓名,用","进行拼接
        String enameString = employees.stream().map(employee -> employee.getEname()).collect(Collectors.joining(","));
        System.out.println(enameString);


        // labels 测试
        System.out.println();
        System.out.println("=============== LABEL TEST ====================");
        System.out.println();
        String labelsStr = labels.stream().collect(Collectors.joining(";"));
        System.out.println(labelsStr);

        // lables 比较
        String l1 = "iresource.fault.io/acceleratorcard";
        String l2 = "iresource.fault.io/sharestorage";
        String l3 = "iresource.fault.io/calcnetwork";
        String l4 = "iresource.fault.io/xxxxx";
        List<String> list2 = Arrays.asList(l2, l3, l1);
        List<String> list3 = Arrays.asList(l1, l2, l4);
        List<String> list4 = Arrays.asList(l1, l2, l3, l4);
        List<String> list5 = Arrays.asList(l4, l2, l3, l4);

        String tLabelStr = labels.stream().sorted().collect(Collectors.joining());
        String tlist2Str = list2.stream().collect(Collectors.joining());
        System.out.println("labels.sort");
        System.out.println(tLabelStr);
        System.out.println("list2");
        System.out.println(tlist2Str);

        boolean ret1 =labels.equals(list2.stream().sorted().collect(Collectors.joining()));
        boolean ret2 = isLabelListEquals(labels, list2);
        boolean ret3 = isLabelListEquals(labels, list3);
        boolean ret4 = isLabelListEquals(labels, list4);
        boolean ret5 = isLabelListEquals(labels, list5);
        boolean ret6 = isLabelListEquals(labels, null);
        System.out.println("labels equals list2.sort: " + ret1);
        System.out.println("labels.sort equals list2.sort: " + ret2);
        System.out.println("labels.sort equals list3.sort: " + ret3);
        System.out.println("labels.sort equals list4.sort: " + ret4);
        System.out.println("labels.sort equals list5.sort: " + ret5);
        System.out.println("labels.sort equals null: " + ret6);

        // isLabelStrEquals
        System.out.println("=====================");
        boolean ret7 = isLabelStrEquals(labels, null);
        boolean ret8 = isLabelStrEquals(labels,
                list2.stream().collect(Collectors.joining(";")));
        boolean ret9 = isLabelStrEquals(labels,
                list2.stream().sorted().collect(Collectors.joining(";")));
        System.out.println("labels.sort:");
        System.out.println(labels.stream().sorted().collect(Collectors.joining(";")));
        System.out.println("labels.sort equals null: " + ret7);
        System.out.println("labels.sort equals list8: " + ret8);
        System.out.println("labels.sort equals list9.sort: " + ret9);


    }

    // 比较数组元素的顺序和值是否相同
    private static boolean isLabelListEquals(List<String> l, List<String> r) {
        /**
         * @titile: isLabelListEquals
         * @description:
         * @param l
         * @param r
         * @return: boolean
         * @author: wangb
         * @date: 2022/9/8 15:48
         */
        

        // defence check
        if (null == l){
            l = new ArrayList<>();
        }
        if (null == r){
            r = new ArrayList<>();
        }
        return l.stream().sorted().collect(Collectors.joining())
                .equals(r.stream().sorted().collect(Collectors.joining()));
    }

    private static boolean isLabelStrEquals(List<String> l, String r) {


        // defence check
        if (null == l){
            l = new ArrayList<>();
        }

        return l.stream().sorted().collect(Collectors.joining(";"))
                .equals(r);
    }

}