JDK8新特性之Stream流的常用方法

前言

众所周知,在Jdk1.8中包含了很多的新特性,例如: Lambda表达式接口的默认方法和静态方法方法引用OptionalStream等很多的新特性或者语法糖,而今天这篇文章着重讲解一下 Stream 流相关的常用方法。

何为Stream流

  • Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
  • Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
  • Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
  • 这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
  • 元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

案例集锦

注意一:首先我们先预先定义一个实体类,Student类,里面有姓名、年龄等若干个属性,而下面的所有案例全都基于此实体类做讲解!

注意二根据这个实体类,我们new出三个学生对象,并设置各自的属性,然后添加到了studentList 集合中,以下所有案例,全部基于此集合讲解!

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
public class Student {
// 姓名
private String name;
// 年龄
private Integer age;
// 性别 1-男 0-女
private Short sex;
// 体重 单位-g
private BigDecimal weight;
// 爱好
private List<String> likeList;

// ....忽略get/set,自己测试请记得添加


// 学生对象集合
private static List<Student> studentList = new ArrayList<>();
// 往集合添加数据
static {
Student student1 = new Student();
student1.setName("小明");
student1.setAge(15);
student1.setSex(Short.parseShort("1"));
student1.setWeight(new BigDecimal("60"));
student1.setLikeList(Arrays.asList("羽毛球","篮球"));

Student student2 = new Student();
student2.setName("小明");
student2.setAge(18);
student2.setSex(Short.parseShort("1"));
student2.setWeight(new BigDecimal("65"));
student2.setLikeList(Arrays.asList("排球","足球"));

Student student3 = new Student();
student3.setName("小红");
student3.setAge(10);
student3.setSex(Short.parseShort("0"));
student3.setWeight(new BigDecimal("55"));
student3.setLikeList(Arrays.asList("足球","乒乓球"));

studentList.add(student1);
studentList.add(student2);
studentList.add(student3);
}
}

1、只单取出姓名属性并去重返回结果

1
2
List<String> nameList = studentList.stream().map(Student::getName).distinct().collect(Collectors.toList());
System.out.println(nameList);

2、取出年龄最大的学生

1
2
Student student = studentList.stream().max(Comparator.comparing(Student::getAge)).orElse(null);
System.out.println(student);

3、计算出性别为男(sex == 1)的学生总数

1
2
long count = studentList.stream().filter(e -> e.getSex().equals(Short.parseShort("1"))).count();
System.out.println(count);

4、分别计算体重和年龄的总和

1
2
3
4
// 体重总和
BigDecimal weightSum = studentList.stream().map(Student::getWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
// 年龄总和
int ageSum = studentList.stream().mapToInt(Student::getAge).sum();

5、根据年龄正序从小到大排序,如果年龄属性为null,则排末尾

1
2
List<Student> collect = studentList.stream().sorted(Comparator.comparing(Student::getAge, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());
System.out.println(collect);

6、根据姓名分组,并计算每个姓名下的体重和年龄总和

1
2
3
4
// 每组体重总和
Map<String, BigDecimal> groupObj1 = studentList.stream().collect(Collectors.groupingBy(Student::getName, Collectors.mapping(Student::getWeight, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
// 每组年龄总和
Map<String, Integer> groupObj2 = studentList.stream().collect(Collectors.groupingBy(Student::getName, Collectors.mapping(Student::getAge,Collectors.reducing(0, Integer::sum))));

7、根据多个条件进行分组

1
2
3
4
Map<List<Object>, List<Student>> groupObj = studentList.stream().collect(Collectors.groupingBy(e -> {
return Arrays.asList(e.getName(), e.getAge());
}));
// PS: 也可也使用拼接写法,不用list接收

8、将集合中的姓名属性为维度进行去重并返回新集合

1
ArrayList<Student> collect = studentList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getName))), ArrayList::new));

9、将集合中年龄当作key,姓名当作value重新组装返回Map类型

1
Map<Integer, String> collect = studentList.stream().collect(Collectors.toMap(Student::getAge, Student::getName));

10、根据姓名分组,且取出每组中体重最重的那位学生

1
2
3
Map<String, Student> groupMax = studentList.stream().collect(Collectors.toMap(Student::getName,
Function.identity(), (c1, c2) -> c1.getWeight().compareTo(c2.getWeight()) > 0 ? c1 : c2));
System.out.println(groupMax);

11、将学生集合(studentList)中的爱好likeList集合属性的提取成一个单独list并去重

1
2
List<String> likeList = studentList.stream().flatMap(x -> x.getLikeList().stream()).distinct().collect(Collectors.toList());
System.out.println(likeList);

12、根据姓名分组求分组体重之和,然后再根据value倒叙排序map

1
2
3
4
5
6
7
8
9
10
Map<String, BigDecimal> groupObj = studentList.stream().collect(Collectors.groupingBy(Student::getName, Collectors.mapping(Student::getWeight, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
// 排序前值
System.out.println(groupObj);
// 开始排序
Map<String, BigDecimal> result = new LinkedHashMap<>();
Comparator<Map.Entry<String, BigDecimal>> entryComparator = Map.Entry.comparingByValue();
entryComparator = entryComparator.reversed();
groupObj.entrySet().stream().sorted(entryComparator.reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
// 根据value排序后的值
System.out.println(result);

讲在末尾

以上就是Jdk1.8中新特性之 Stream 流的以下常用方法,Stream流在实际开发业务中其实用的场景非常之多,好记性不如烂笔头,因此写下这篇博文,以防止遗忘,或许对我对你对他都有帮助。