在java8之前我们要操作集合首先要去遍历集合然后在根据条件筛选出符合的元素放到一个新的集合中去,当需要多次这样操作后,代码的可读性会下降而且对于使用者也不够友好。java8出现后,提供了一个新的类库位于:java.util.stream包下,在这个类库中提供了大量的Stream Api供开发者使用,大大简化了操作集合代码的复杂度。从开发者的角度使用Stream Api操作集合可以让程序员更加随意的对集合进行分组过滤,提高的工作的效率并且代码也变的更加的简洁和易于维护。
一、获取Stream对象
在java8中的Collection接口中提供了两个方法可以获取Stream,这个两个方法分别是stream()方法和parallelStream()方法。其中stream()方法返回的是一个顺序Srteam(单线程);parallelStream()方法返回的是一个并行Stream(多线程)。接下来我主要介绍顺序Stream。
二、Stream中的常用Api
1.筛选
在Stream Api中使用filter来进行集合的筛选,Stream<T> filter(Predicate<? super T> predicate)返回由与此给定谓词匹配的此流的元素组成的流。下面我通过一个例子来介绍stream的使用方法。例如现在我有一个list集合,现在我需要筛选出学生年龄小于30岁的学生,在java8之前我们是通过这样的方法来实现的。
public class TestStream { private final static List<Student> studentList = new ArrayList<Student>(); static{ Student student1 = new Student("zhangsan",20); Student student2 = new Student("lisi",21); Student student3 = new Student("wangwu",22); Student student4 = new Student("zhouliu",23); Student student5 = new Student("jiju",24); Student student6 = new Student("babu",40); Student student7 = new Student("yaue",31); Student student8 = new Student("xixi",30); studentList.add(student1); studentList.add(student2); studentList.add(student3); studentList.add(student4); studentList.add(student5); studentList.add(student6); studentList.add(student7); studentList.add(student8); } public static List<Student> getList(){ return studentList; } public static void main(String[] args) { List<Student> studentList = getList(); //需求:筛选出30岁以下的学生 //jdk8之前 List<Student> newStudentList =new ArrayList<Student>(); for (Student student : studentList) { if(student.getAge()<30){ newStudentList.add(student); } } newStudentList.stream().forEach(e->System.out.println(e.getName()+"----"+e.getAge())); } } 控制台输出: zhangsan----20 lisi----21 wangwu----22 zhouliu----23 jiju----24
在使用了java8之后代码可以简化为:
public static void main(String[] args) { List<Student> studentList = getList(); //需求:筛选出30岁以下的学生 //jdk8 List<Student> newStudentList =new ArrayList<Student>(); newStudentList = studentList.stream().filter(e->e.getAge()<30).collect(Collectors.toList()); newStudentList.stream().forEach(e->System.out.println(e.getName()+"----"+e.getAge())); }
其中filter起到了过滤的作用,有点类似于sql语句的where条件。
2.切片
有时我们需要限定获取集合中的元素个数,在Stream Api中提供了两个方法:limit(n)和skip(n)。Stream<T> limit(long maxSize)返回由该流的元素组成的流,截断长度不能超过maxSize。Stream<T> skip(long n)在丢弃流的第一个n元素后,返回由该流的n元素组成的流。 如果此流包含少于n元素,那么将返回一个空流。limit和skip正好是互补的。示例代码:
List<Student> studentList = getList(); //需求:筛选出30岁以下的学生 //jdk8 List<Student> newStudentList =new ArrayList<Student>(); newStudentList = studentList.stream().filter(e->e.getAge()<30).limit(2).collect(Collectors.toList()); newStudentList.stream().forEach(e->System.out.println(e.getName()+"----"+e.getAge()));
控制台输出:
zhangsan----20
lisi----21
3.去重
在stream中使用distinct来实现集合元素的去重。distinct是通过Object的equals方法去重的。这个方法比较的简单,我就不做代码的演示了。
4.映射
还是上面的例子,现在我们需要获取年龄是30岁以下的学生的姓名,这时就需要使用Sream Api中的map方法。<R> Stream<R> map(Function<? super T,? extends R> mapper)返回由给定函数应用于此流的元素的结果组成的流。在java8之前我们是这样实现的,代码如下:
List<String> studentNames = new ArrayList<String>(); for (Student student : studentList) { if(student.getAge()<30){ studentNames.add(student.getName()); } } studentNames.stream().forEach(System.out::println);
java8之后我们可以把代码简化为:
List<String> studentNames = new ArrayList<String>(); studentNames = studentList.stream().filter(e->e.getAge()<30).map(Student::getName).collect(Collectors.toList()); studentNames.stream().forEach(System.out::println);
5.排序
java8中提供了俩个sort方法,一个是无参的;另一个需要传一个自定义的Comparator。代码实例如下:
public static void main(String[] args) { List<Student> studentList = getList(); studentList = studentList.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList()); studentList.forEach(e->System.out.println(e.getName()+"----"+e.getAge())); }
这里我是根据学生的年龄从大到小排列如果去掉reversed()表示从小到大排列。
java8中的stream api可以让我们非常方便的处理集合,有点类似于sql语句,大大的提高了我们开发的效率。