现在越来越多的公司开始使用jdk8了,jdk8有许多新特性,其中一个特性便是流式处理,进而有好多对于集合的便利操作
我自己也是刚开始熟悉jdk8,便在此记录一些基本的关于集合的操作 至于一些理论上的东西我就不写了,某度一大堆,因为一点点介绍每段的含义来路也不是一篇博客就能写完的,我只会简单说一下每段的意思,废话不多说,上代码
先创建一下的练习会用到的类
package com.chunying.lambda; /** * @author chunying */ public class Student { private final String name; private final Integer age; private final Gender gender; public Student(String name, Integer age , Gender gender) { this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public Integer getAge() { return age; } public Gender getGender() { return gender; } public enum Gender{MALE , FEMALE}; }
package com.chunying.lambda; import java.util.Arrays; import java.util.List; /** * @author chunying */ public class LambdaDemo { List<Student> data = Arrays.asList( new Student("张三" ,23 , Student.Gender.MALE), new Student("李四" ,24 , Student.Gender.MALE), new Student("王五" ,24 , Student.Gender.FEMALE), new Student("赵六" ,23 , Student.Gender.FEMALE) ); }
这里我创建了一个学生类以及学生类的集合,以下的所有操作都将通过它们来完成
首先第一个:获取所有男性的学生集合
如果没有jdk8我们会怎样写呢?
@Test public void fun1() { //所有男性集合 List<Student> result = new ArrayList<>(); for(Student student : data) { if(student.getGender().equals(Student.Gender.MALE)) { result.add(student); } } System.out.println(result); }
需要遍历集合,一个一个去判断是否符合我们的条件,如果数据量比较大,或者判断条件比较多,那么可能在单线程情况下就会比较慢。多线程:就要和synchronized打交道,烦不胜烦,一不注意没处理好就会出问题
jdk8帮我们解决了这个问题
我们先看代码
@Test public void fun2() { List<Student> result = data.stream() .filter(student -> student.getGender().equals(Student.Gender.MALE)) .collect(Collectors.toList()); System.out.println(result); }
首先lambda表达式的基础我就不说了,我会在其他文章补充,这里不是重点,这个结果和上面是一样的
首先stream()方法,将集合变成了流,
fileter()方法,过滤到我们所需要的,
最后collect(Collectors.toList())将得到的流对象转换为集合。
第二个:将所有的学生按照年纪分组,并且获取到所有的年纪的集合
首先还是看没有jdk8怎么做
@Test public void fun3() { List<Integer> allAges = new ArrayList<>(); Map<Integer , List<Student>> studentByAge = new HashMap<>(); for(Student student : data) { Integer age = student.getAge(); if(!allAges.contains(age)) { allAges.add(age); } List<Student> temp = studentByAge.get(age); if(temp == null) { temp = new ArrayList<>(); temp.add(student); studentByAge.put(age , temp); }else { temp.add(student); } } System.out.println(allAges); System.out.println(studentByAge); }
其中temp集合是完全没有用的中间计算集合。非常麻烦而且不易读
我们看jdk8怎么做
@Test public void fun4() { List<Integer> allAges = data.stream().map(Student::getAge) .distinct() .collect(Collectors.toList()); Map<Integer , List<Student>> studentByAge = data.stream().collect(Collectors.groupingBy(Student::getAge)); System.out.println(allAges); System.out.println(studentByAge); }
先看获取年纪,通过map()方法获取到所有的年纪,distinct()去重,collect转换成集合
分组这边,比较上面这里仅仅一行代码,通过groupingBy()把所有的学生按照年纪分组即可。
第三个:所有学生按照姓名分组(假设没有重名的)
首先还是看没有jdk8怎么做。
@Test public void fun5() { Map<String , Student> studentByName = new HashMap<>(); for(Student student : data) { studentByName.put(student.getName() , student); } }
接下来看jdk8
@Test public void fun6() { Map<String , Student> studentByName = data.stream().collect(Collectors.toMap(Student::getName , student->student)); }
这里用到了toMap()方法,不多解释了
第四个:集合遍历
jdk8之前集合遍历,单列集合都可以通过for(Object o : data){}来遍历,底层无非还是iterator。
map就麻烦了,一种是通过拿到keySet再去拿每一个值,一种是通过entrySet拿到每一个entry对象,再去获取键值。操作很不方便
直接看jdk8的结合遍历
@Test public void fun6() { Map<String , Student> studentByName = data.stream().collect(Collectors.toMap(Student::getName , student->student)); data.forEach(student -> { System.out.println(student); }); studentByName.forEach((name , student)-> { System.out.println(name + "-" + student); }); }怎么样是不是方便了很多?
第五个:排序以及类型转换
jdk8以前的排序大多是通过Comparator来排序,每次要定义排序规则或者比较器,很不方便
我们看jdk8
@Test public void fun7() { //将所有学生按照年级排序并返回学生集合 List<Student> result = data.stream() .sorted(Comparator.comparing(Student::getAge)) .collect(Collectors.toList()); System.out.println(result); }
是不是很方便的。
常用的操作就这些,我就先记录到这里。