发布时间:2023-04-21 15:00
当需要对多个元素进行操作的时候,考虑到性能及便利性,会拼好一个“模型”步骤方案,再按照方案去执行它。
此处中间体的Lazy操作就相当于下面代码的filter
组合操作,集合元素并没有真正被处理。只有当终结方法forEach执行的时候,整个模型才会按照指定策略执行操作。
这就是Lambda的延迟执行特性。
列举一些常见的中间操作和终结操作
中间操作(Intermediate):
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered、concat
终结操作(Terminal):
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 iterator anyMatch、 allMatch、 noneMatch、 findFirst、 findAny
如果我们强行再终结操作之后继续对stream进行操作的话,会报出IllegalStateException
异常:
// List转换为Stream流
List<String> list = new ArrayList<>();
Stream<String> streamlist = list.stream();
// Set转换为Stream流
Set<String> set = new HashSet<>();
Stream<String> streamSet = set.stream();
// 获取Set的键
Map<String, String> map = new HashMap<>();
map.put("123","123");
Stream<String> streamKeySet = map.keySet().stream();
// 获取Collection的值
Collection<String> collection = map.values();
Stream<String> streamCollection = collection.stream();
// 获取键值对(键与值之间的映射关系entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream = entries.stream();
// 把数组转换为Stream流
Stream<Integer> streamArr01 = Stream.of(1, 2, 3, 4, 5);
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> streamArr02 = Stream.of(arr);
String[] arr2 = {"a", "bb", "ccc"};
Stream<String> streamArr03 = Stream.of(arr2);
该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理:
void forEach(Consumer<? super T> action);
之前的博客中有讲到:Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据。
该方法可以将流中的元素映射到另一个流中:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
之前的博客中有讲到:Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。主要用的是里面唯一的抽象方法 R apply(T t);
,它将一种T类型转换成为R类型,这种转换的动作,就称为“映射”。
该方法可以将一个流转换成另一个子集流:
Stream<T> filter(Predicate<? super T> predicate);
之前的博客中有讲到:Predicate唯一的抽象方法boolean test(T t);
,将会产生一个boolean值结果,代表指定的条件是否满足。如果结果为true,那么Stream流的 filter 方法将会留用元素;如果结果为false,那么 filter 方法将会舍弃元素。
该方法可以跳过前n个,然后取到一个截取之后的新流,具体示例如下: