3)匹配
Stream 类提供了三个方法可供进行元素匹配,它们分别是:
anyMatch(),只要有一个元素匹配传入的条件,就返回 true。
allMatch(),只有有一个元素不匹配传入的条件,就返回 false;如果全部匹配,则返回 true。
noneMatch(),只要有一个元素匹配传入的条件,就返回 false;如果全部匹配,则返回 true。
public class MatchStreamDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("周杰伦"); list.add("王力宏"); list.add("陶喆"); list.add("林俊杰"); boolean anyMatchFlag = list.stream().anyMatch(element -> element.contains("王")); boolean allMatchFlag = list.stream().allMatch(element -> element.length() > 1); boolean noneMatchFlag = list.stream().noneMatch(element -> element.endsWith("沉")); System.out.println(anyMatchFlag); System.out.println(allMatchFlag); System.out.println(noneMatchFlag); } }
因为“王力宏”以“王”字开头,所以 anyMatchFlag 应该为 true;因为“周杰伦”、“王力宏”、“陶喆”、“林俊杰”的字符串长度都大于 1,所以 allMatchFlag 为 true;因为 4 个字符串结尾都不是“沉”,所以 noneMatchFlag 为 true。
程序输出的结果如下所示:
true
true
true
1
2
3
4)组合
reduce() 方法的主要作用是把 Stream 中的元素组合起来,它有两种用法:
Optional<T> reduce(BinaryOperator<T> accumulator)
没有起始值,只有一个参数,就是运算规则,此时返回 Optional。
T reduce(T identity, BinaryOperator<T> accumulator)
有起始值,有运算规则,两个参数,此时返回的类型和起始值类型一致。
来看下面这个例子。
public class ReduceStreamDemo { public static void main(String[] args) { Integer[] ints = {0, 1, 2, 3}; List<Integer> list = Arrays.asList(ints); Optional<Integer> optional = list.stream().reduce((a, b) -> a + b); Optional<Integer> optional1 = list.stream().reduce(Integer::sum); System.out.println(optional.orElse(0)); System.out.println(optional1.orElse(0)); int reduce = list.stream().reduce(6, (a, b) -> a + b); System.out.println(reduce); int reduce1 = list.stream().reduce(6, Integer::sum); System.out.println(reduce1); } }
运算规则可以是 Lambda 表达式(比如 (a, b) -> a + b),也可以是类名::方法名(比如 Integer::sum)。
程序运行的结果如下所示:
6
6
12
12
1
2
3
4
0、1、2、3 在没有起始值相加的时候结果为 6;有起始值 6 的时候结果为 12。
03、转换流
既然可以把集合或者数组转成流,那么也应该有对应的方法,将流转换回去——collect() 方法就满足了这种需求。
public class CollectStreamDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("周杰伦"); list.add("王力宏"); list.add("陶喆"); list.add("林俊杰"); String[] strArray = list.stream().toArray(String[]::new); System.out.println(Arrays.toString(strArray)); List<Integer> list1 = list.stream().map(String::length).collect(Collectors.toList()); List<String> list2 = list.stream().collect(Collectors.toCollection(ArrayList::new)); System.out.println(list1); System.out.println(list2); String str = list.stream().collect(Collectors.joining(", ")).toString(); System.out.println(str); } }
toArray() 方法可以将流转换成数组,你可能比较好奇的是 String[]::new,它是什么东东呢?来看一下 toArray() 方法的源码。
<A> A[] toArray(IntFunction<A[]> generator);
1
也就是说 String[]::new 是一个 IntFunction,一个可以产生所需的新数组的函数,可以通过反编译字节码看看它到底是什么:
String[] strArray = (String[])list.stream().toArray((x$0) -> { return new String[x$0]; }); System.out.println(Arrays.toString(strArray));
也就是相当于返回了一个指定长度的字符串数组。
当我们需要把一个集合按照某种规则转成另外一个集合的时候,就可以配套使用 map() 方法和 collect() 方法。
List<Integer> list1 = list.stream().map(String::length).collect(Collectors.toList());
通过 stream() 方法创建集合的流后,再通过 map(String:length) 将其映射为字符串长度的一个新流,最后通过 collect() 方法将其转换成新的集合。
Collectors 是一个收集器的工具类,内置了一系列收集器实现,比如说 toList() 方法将元素收集到一个新的 java.util.List 中;比如说 toCollection() 方法将元素收集到一个新的 java.util.ArrayList 中;比如说 joining() 方法将元素收集到一个可以用分隔符指定的字符串中。
来看一下程序的输出结果:
[周杰伦, 王力宏, 陶喆, 林俊杰]
[3, 3, 2, 3]
[周杰伦, 王力宏, 陶喆, 林俊杰]
周杰伦, 王力宏, 陶喆, 林俊杰