java流库
# 从迭代到流的操作
在处理集合时,我们通常会迭代遍历它的元素,并在每个元素上执行某项操作。比如:对一个列表中的很多个长单词进行统计计数:
@Test
public void testStream1() {
List<String> words = new ArrayList<>();
words.add("springframework");
words.add("SpringRunner");
words.add("MainApplication");
words.add("RunWith");
int count = 0;
for (String word : words) {
if (word.length() > 12) {
count++;
}
}
System.out.println(count);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
现在我们用流来操作
@Test
public void testCountWordsByStream() {
List<String> words = new ArrayList<>();
words.add("springframework");
words.add("SpringRunner");
words.add("MainApplication");
words.add("RunWith");
long count = words.stream().filter(w -> w.length() > 12).count();
System.out.println(count);
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
现在我们不必去扫描整个代码去查找过滤和计数操作,方法名就可以直接告诉我们其代码意欲何为。而且循环需要非常详细地指定操作的顺序,而流却能够以其想要的任何方式来调度这些操作,只要是结果正确即可。
Stream<T> filter(Predicate<? super T> predicate);
// 产生一个流,其中包含当前流中满足 predicate 的所有元素
1
2
3
2
3
long count();
// 产生当前流中的元素的数量,这是一个终止的操作
1
2
3
2
3
# 迭代的演进
先介绍一下 lambda 表达式
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 语言表达能力得到了提升。
然后以一个比较器来进行比较优化点:
# 匿名内部类
一个比较器
// 匿名内部类
public void test1() {
Comparator<Integer> com = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 有用的代码就这一句
return Integer.compare(o1, o2);
}
};
TreeSet<Integer> ts = new TreeSet<>(com);
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
其实有用的就一个比较的代码。使用 Lambda 表达式来简写
public void test2() {
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
TreeSet<Integer> ts = new TreeSet<>(com);
}
1
2
3
4
2
3
4
# 演进
需求:获取员工工资大于 5000 的员工信息
我们先建立一个实体类
package com.wx.java8;
public class Employee {
private String name;
private int age;
private double salary;
public Employee(String name, int age, double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public Employee() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
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
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
然后造一个员工集合
List<Employee> employeeList = Arrays.asList(
new Employee("张三", 18, 999.99),
new Employee("李四", 36, 21321),
new Employee("王五", 39, 33333.33),
new Employee("赵六", 29, 7777.77)
);
1
2
3
4
5
6
2
3
4
5
6
# 第一种:遍历的角度
public List<Employee> filterEmployee(List<Employee> list) {
// 遍历角度来获取
List<Employee> emps = new ArrayList<>();
for (Employee employee : list) {
if (employee.getSalary() > 5000) {
emps.add(employee);
}
}
return emps;
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 第二种:接口形式
public interface MyPredicate<T> {
public boolean test(T t);
}
1
2
3
2
3
实现一个判断的方法
public class FilterEmployeeBySalary implements MyPredicate<Employee> {
@Override
public boolean test(Employee employee) {
return employee.getSalary() > 5000;
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
然后在进行遍历的时候使用这个方法进行判断,代替上述遍历的判断一步
public List<Employee> filterEmployee2(List<Employee> list, MyPredicate<Employee> myPredicate) {
List<Employee> emps = new ArrayList<>();
for (Employee employee : list) {
if (myPredicate.test(employee)) {
emps.add(employee);
}
}
return emps;
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 第三种:使用匿名内部类来实现接口
上面使用额外的类来实现接口,如果判断越来越多,类也会越来越多,维护也比较麻烦,所以使用匿名内部类来实现。
public void test5() {
List<Employee> employees = filterEmployee2(employeeList, new MyPredicate<Employee>() {
@Override
public boolean test(Employee employee) {
// 最后还是绕到这里,有用的就这一句,但是代码量很多,可读性降低了
return employee.getSalary() > 5000;
}
});
for (Employee employee : employees) {
System.out.println(employee);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 第四种:使用 lambda 表达式来简化代码
public void test6() {
List<Employee> employees = filterEmployee2(employeeList, (e) -> e.getSalary() <= 5000);
// 打印遍历结果
employees.forEach(System.out::println);
}
1
2
3
4
5
2
3
4
5
# 第五种:使用Stream API
public void test7() {
employeeList.stream().filter((e) -> e.getSalary() > 5000).forEach(System.out::println);
}
1
2
3
2
3
编辑 (opens new window)
上次更新: 2022/01/18, 00:33:47