Java Stream函数式编程接口最初在Java 8中引入,并且与 lambda 一起成为Java开发里程碑式的功能特性,它极大的方便了开放人员处理集合类数据的效率。

Java Stream就是一个数据流经的管道,并且在管道中对数据进行操作,然后流入下一个管道。有学过linux 管道的同学应该会很容易就理解。在没有Java Stram之前,对于集合类的操作,更多的是通过for循环。大家从后文中就能看出Java Stream相对于for 循环更加简洁、易用、快捷。
管道的功能包括:Filter(过滤)、Map(映射)、sort(排序)等,集合数据通过Java Stream管道处理之后,转化为另一组集合或数据输出。
先来看一个例子:
- List
nameStrs = Arrays.asList("Monkey", "Lion", "Giraffe","Lemur"); -
- List
list = nameStrs.stream() - .filter(s -> s.startsWith("L"))
- .map(String::toUpperCase)
- .sorted()
- .collect(toList());
- System.out.println(list);
最终的输出结果是:[LEMUR, LION]。
当然如果想要根据其他规则进行排序,可以使用 sorted(Comparator) 方法,并提供一个自定义比较器来指定排序的规则。比如可以使用 sorted((str1, str2) -> str1.length() - str2.length()) 来按字符串长度进行排序。
- import java.util.Comparator;
-
- public class StringLengthComparator implements Comparator
{ - @Override
- public int compare(String str1, String str2) {
- return str1.length() - str2.length();
- }
- }
创建了一个名为 StringLengthComparator 的类,它实现了 Comparator 接口。这个接口要求我们实现 compare 方法来定义元素之间的排序规则。
在 compare 方法中,使用 str1.length() - str2.length() 来比较两个字符串的长度。如果 str1 的长度小于 str2 的长度,返回一个负值。如果 str1 的长度大于 str2 的长度,返回一个正值。如果 str1 和 str2 的长度相等,返回 0。通过传递 new StringLengthComparator() 给 sorted() 方法,可以按照字符串长度进行排序。
- List
sortedList = nameStrs.stream() - .filter(s -> s.startsWith("L"))
- .map(String::toUpperCase)
- .sorted(new StringLengthComparator())
- .collect(Collectors.toList());
-
- System.out.println(sortedList);
当然,使用Java 8之前的方法来实现对一个string列表进行排序:
- List
names = Arrays.asList("peter", "anna", "mike", "xenia"); - Collections.sort(names, new Comparator
() { - @Override
- public int compare(String a, String b) {
- return b.compareTo(a);
- }
- });
使用 Lambda 表达式后的效果是:
- Collections.sort(names, (String a, String b) -> {
- return b.compareTo(a);
- });
- // 只有一条逻辑语句,可以省略大括号
- Collections.sort(names, (String a, String b) -> b.compareTo(a));
- // 可以省略入参类型
- Collections.sort(names, (a, b) -> b.compareTo(a));
使用Stream.of()方法,将数组转换为管道流。
- String[] array = {"Monkey", "Lion", "Giraffe", "Lemur"};
- Stream
nameStrs2 = Stream.of(array); -
- Stream
nameStrs3 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur");
通过调用集合类的stream()方法,将集合类对象转换为管道流。
- List
list = Arrays.asList("Monkey", "Lion", "Giraffe", "Lemur"); - Stream
streamFromList = list.stream(); -
- Set
set = new HashSet<>(list); - Stream
streamFromSet = set.stream();
通过Files.lines方法将文本文件转换为管道流,Paths.get()方法作用就是获取文件,是Java NIO的API也就是说:我们可以很方便的使用Java Stream加载文本文件,然后逐行的对文件内容进行处理。
Stream lines = Files.lines(Paths.get("file.txt"));
一旦将数组或一组值转换为流,你就可以使用流的各种操作方法对其进行处理和操作。下面是一些示例操作:
①、遍历流中的元素:
- Stream
nameStrs2 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); - nameStrs2.forEach(System.out::println);
②、过滤流中的元素:
- Stream
nameStrs2 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); - Stream
filteredStream = nameStrs2.filter(s -> s.startsWith("L"));
③、对流中的元素进行转换:
- Stream
nameStrs2 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); - Stream
upperCaseStream = nameStrs2.map(String::toUpperCase);
④、对流中的元素进行排序:
- Stream
nameStrs2 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); - Stream
sortedStream = nameStrs2.sorted();
⑤、对流中的元素进行聚合操作:
- Stream
nameStrs2 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); - Optional
longestString = nameStrs2.max(Comparator.comparingInt(String::length));
⑥、收集流中的元素到集合中:
- Stream
nameStrs2 = Stream.of("Monkey", "Lion", "Giraffe", "Lemur"); - List
stringList = nameStrs2.collect(Collectors.toList());