Java 8 - Stream流骚操作解读 ゝ一世哀愁。 2022-11-06 05:51 211阅读 0赞 ### 文章目录 ### * 分类 * * 中间操作 * 终端操作 * 使用Stream流 * * 筛选和切片 * * 用谓词筛选 filter * 筛选各异的元素 distinct * 截短流 limit * 跳过元素 skip * 映射 * * 对流中每一个元素应用函数 map * 流的扁平化 flatMap * * 尝试使用map 和 Arrays.stream() 【未解决】 * 使用flatMap 【解决】 * 查找和匹配 * * 检查谓词中是否至少匹配一个元素 anyMatch * 检查谓词中是否匹配所有元素 allMatch * 检查谓词中都不匹配所有元素 noneMatch * * 什么是短路求值 * 查找元素 findAny * 查找第一个元素 findFirst * 何时使用 findFirst 和 findAny ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70] -------------------- # 分类 # `java.util.stream.Stream` 中的 Stream 接口定义了许多操作。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 1] 我们来看个例子 ![在这里插入图片描述][20210308115130430.png] 可以分为两大类操作 * filter 、 map 和 limit 可以连成一条流水线 * collect 触发流水线执行并关闭它 可以连接起来的流操作称为**中间操作**,关闭流的操作称为**终端操作** ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 2] -------------------- ## 中间操作 ## 诸如 filter 或 sorted 等中间操作会返回另一个流。这让多个操作可以连接起来形成一个查询。重要的是,除非流水线上触发一个终端操作,否则中间操作不会执行任何处理 。 这是因为中间操作一般都可以合并起来,在终端操作时一次性全部处理。 为了搞清楚流水线中到底发生了什么,我们把代码改一改,让每个Lambda都打印出当前处理的数据 /** * 需求: 输出小于400的Dish的名字 , 按照卡路里从第到高输出 * @param dishList * @return */ public static List<String> getDiskNamesByStream2(List<Dish> dishList) { return dishList.stream() .filter(dish -> { System.out.println("filtering:" + dish.getName()); return dish.getCalories() <400 ; }) .map(dish -> { System.out.println("mapping:" + dish.getName()); return dish.getName(); }) .limit(3) .collect(Collectors.toList()); } 仅限于自己学习的时候这么写哈 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 3] 输出 filtering:pork mapping:pork filtering:beef mapping:beef filtering:chicken mapping:chicken [pork, beef, chicken] 这里面有好几种优化利用了流的延迟性质。 * 第一,尽管很高于300卡路里的数据,但只选出了前三个。 因为 limit 操作和一种称为**短路**的技巧 * 第二,尽管 filter 和 map 是两个独立的操作,但它们合并到同一次遍历中了(我们把这种技术叫作**循环合并**) -------------------- ## 终端操作 ## 终端操作会从流的流水线生成结果。其结果是任何不是流的值,比如 List 、 Integer ,甚至 void 。例如,在下面的流水线中, forEach 是一个返回 void 的终端操作,它会对源中的每道菜应用一个Lambda。把 `System.out.println` 传递给 forEach ,并要求它打印出由 menu 生成的流中的每一个 Dish dishList.stream().forEach(System.out::println); -------------------- # 使用Stream流 # 流的使用一般包括三件事: * 一个数据源(如集合)来执行一个查询; * 一个中间操作,形成一条流的流水线; * 一个终端操作,执行流水线,并能生成结果 流的流水线背后的理念类似于构建器模式。 在构建器模式中有一个调用链用来设置一套配置(对流来说这就是一个**中间操作**链),接着是调用 built 方法(对流来说就是**终端操作**)。 列一下之前的代码中我们用到的流操作,当然了不止这些 【中间操作】 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 4] 【终端操作】 ![在这里插入图片描述][20210308140321852.png] 还有很多模式,过滤、切片、查找、匹配、映射和归约可以用来表达复杂的数据处理查询。 ![在这里插入图片描述][20210308140536397.gif_pic_center] 来看看其他的,当然了不全哈 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 5] -------------------- ## 筛选和切片 ## 如何选择流中的元素? 用谓词筛选,筛选出各不相同的元素,忽略流中的头几个元素,或将流截短至指定长度. ### 用谓词筛选 filter ### Streams 接口支持 filter 方法 ,该操作会接受一个谓词(一个返回boolean 的函数)作为参数,并返回一个包括所有符合谓词的元素的流. 需求: 筛选出所有素菜 ![在这里插入图片描述][20210308163454436.png] /** * 需求: 输出所有的素菜 * @param dishList * @return */ public static List<Dish> getVegetarianByStream(List<Dish> dishList){ return dishList.stream() .filter(Dish::isVegetarian) .collect(Collectors.toList()); } ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 6] -------------------- ### 筛选各异的元素 distinct ### 流还支持一个叫作 distinct 的方法,它会返回一个元素各异(根据流所生成元素的hashCode 和 equals 方法实现)的流。 需求: 给定一组数据,筛选出列表中所有的偶数,并确保没有重复 public static void testDistinct(){ Arrays.asList(1,2,1,3,3,2,4) .stream() .filter(i -> i%2 ==0) .distinct() .forEach(System.out::println); } ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 7] -------------------- ### 截短流 limit ### 流支持 limit(n) 方法,该方法会返回一个不超过给定长度的流。所需的长度作为参数传递给 limit 。如果流是有序的,则最多会返回前 n 个元素。 需求: 选出热量超过300卡路里的头三道菜 /** * 选出热量超过300卡路里的头三道菜 * @param dishes * @return */ public static List<String> getTop3HighCa(List<Dish> dishes) { return dishes.stream() .filter(d -> d.getCalories() > 300) .limit(3) .collect(Collectors.toList()); } 展示了 filter 和 limit 的组合。可以看到,该方法只选出了符合谓词的头三个元素,然后就立即返回了结果。 请注意 limit 也可以用在无序流上,比如源是一个 Set 。这种情况下, limit 的结果不会以任何顺序排列。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 8] -------------------- ### 跳过元素 skip ### 流还支持 skip(n) 方法,返回一个扔掉了前 n 个元素的流。如果流中元素不足 n 个,则返回一 个空流。请注意, limit(n) 和 skip(n) 是互补的 需求: 跳过超过300卡路里的头两道菜,并返回剩下的 /** * 需求: 跳过超过300卡路里的头两道菜,并返回剩下的 * @param dishes * @return */ public static List<Dish> skipTop2Over300Carl(List<Dish> dishes) { return dishes.stream().filter(d->d.getCalories()>300) .skip(2) .collect(Collectors.toList()); } ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 9] -------------------- ## 映射 ## 一个非常常见的数据处理套路就是从某些对象中选择信息。比如在SQL里,你可以从表中选择一列。Stream API也通过 map 和 flatMap 方法提供了类似的工具。 ![在这里插入图片描述][20210308191941581.gif_pic_center] ### 对流中每一个元素应用函数 map ### 流支持 map 方法,它会接受一个函数作为参数。这个函数会被应用到每个元素上,并将其映射成一个新的元素(使用映射一词,是因为它和转换类似,但其中的细微差别在于它是“创建一个新版本”而不是去“修改”)。 举个例子 : public static List<String> getMenu(List<Dish> dishes) { return dishes.stream() .map(Dish::getName) .collect(Collectors.toList()); } 功能: 把方法引用 `Dish::getName` 传给了 map 方法来提取流中菜肴的名称。 因为 getName 方法返回一个 String ,所以 map 方法输出的流的类型就是 `Stream<String>` 【再来看个例子 】 给定一个单词列表,想要返回另一个列表,显示每个单词中有几个字母。 怎么做呢?你需要对列表中的每个元素应用一个函数。 这听起来正好该用 map 方法去做!应用的函数应该接受一个单词,并返回其长度。你可以像下面这样,给 map 传递一个方法引用 String::length 来解决这个问题: /** * 给定一个单词列表,想要返回另一个列表,显示每个单词中有几个字母。 * @return */ public static List mapping(){ List<String> list = Arrays.asList("abc","pear","child","artisan"); return list.stream().map(d->d.length()).collect(Collectors.toList()); } 使用方法引用优化 public static List mapping(){ List<String> list = Arrays.asList("abc","pear","child","artisan"); return list.stream().map(String::length).collect(Collectors.toList()); } 那再看个 /** * 需求: 要找出每道菜的名称有多长 * @param dishes * @return */ public static List<Integer> getMenuLength(List<Dish> dishes) { return dishes.stream() .map(Dish::getName) .map(String::length) .collect(Collectors.toList()); } ![在这里插入图片描述][20210308220914350.jpg_pic_center] -------------------- ### 流的扁平化 flatMap ### 我们已经看到如何使用 map 方法返回列表中每个单词的长度了。 让我们扩展一下:对于一张单词表 , 如何返回一张列表 , 列出里面各不相同的字符呢? 怎么实现呢? 是不是可以把每个单词映射成一张字符表,然后调用 distinct 来过滤重复字符, 秒啊 ![在这里插入图片描述][20210308195640101.gif_pic_center] public static List<String[]> test() { List<String> list = Arrays.asList("hello","world"); return list.stream().map(t -> t.split(" ")).distinct().collect(Collectors.toList()) ; } (⊙o⊙)… ,不对。。。。 这个方法的问题在于,传递给 map 方法的Lambda为每个单词返回了一个 `String[] ( String列表)`。因此, map 返回的流实际上是 `Stream<String[]>` 类型的。 我们真正想要的是用`Stream<String>` 来表示一个字符流 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 10] ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 11] 那这么办呢? #### 尝试使用map 和 Arrays.stream() 【未解决】 #### 可以用 flatMap 来解决这个问题!让我们一步步看看怎么解决它。 /** * 需求: 对于一张单词表 , 如何返回一张列表 , 列出里面各不相同的字符呢? * * 错误的写法 * @return */ public static List<Stream<String>> test2() { Stream<String> stream = Arrays.stream(new String[]{ "hello", "world"}); return stream.map(t->t.split(" ")).map(Arrays::stream).distinct().collect(Collectors.toList()); } ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 12] 当前的解决方案仍然搞不定!这是因为,你现在得到的是一个流的列表(更准确地说是`Stream<String>`)。的确,你先是把每个单词转换成一个字母数组,然后把每个数组变成了一个独立的流。 #### 使用flatMap 【解决】 #### /** * 需求: 对于一张单词表 , 如何返回一张列表 , 列出里面各不相同的字符呢? * <p> * 完美 * * @return */ public static List<String> test3() { Stream<String> stream = Arrays.stream(new String[]{ "hello", "world"}); return stream.map(t -> t.split(" ")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList()); } ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 13] 使用 flatMap 方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容 。 所有使用 flatMap(Arrays::stream) 时生成的单个流都被合并起来,即扁平化为一个流 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 14] 一言以蔽之, flatmap 方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流。 -------------------- ## 查找和匹配 ## 另一个常见的数据处理套路是看看数据集中的某些元素是否匹配一个给定的属性。StreamAPI通过 allMatch 、 anyMatch 、 noneMatch 、 findFirst 和 findAny 方法提供了这样的工具。 -------------------- ### 检查谓词中是否至少匹配一个元素 anyMatch ### anyMatch 方法可以回答“流中是否有一个元素能匹配给定的谓词”。 比如,你可以用它来看 /** * 需求: 是否包含素菜 */ public static void isVe(List<Dish> dishes) { if (dishes.stream().anyMatch(Dish::isVegetarian)){ System.out.println("you su cai "); } } anyMatch 方法返回一个 boolean ,因此是一个终端操作. -------------------- ### 检查谓词中是否匹配所有元素 allMatch ### allMatch 方法的工作原理和 anyMatch 类似,但它会看看流中的元素是否都能匹配给定的谓词。 比如,你可以用它来看看所有热量是否都低于1000卡路里 /** * 需求: 看看所有热量是否都低于1000卡路里 */ public static void isHea(List<Dish> dishes) { if (dishes.stream().allMatch(d->d.getCalories()<1000)){ System.out.println("oj8k "); } } -------------------- ### 检查谓词中都不匹配所有元素 noneMatch ### 和 allMatch 相对的是 noneMatch 。它可以确保流中没有任何元素与给定的谓词匹配。 /** * 需求: 没有任何一个卡路里超过1000 */ public static void isHeass(List<Dish> dishes) { if (dishes.stream().noneMatch(d->d.getCalories()>=1000)){ System.out.println("muyou "); } } anyMatch 、 allMatch 和 noneMatch 这三个操作都用到了我们所谓的**短路**,这就是大家熟悉的Java中 && 和 || 运算符短路在流中的版本 ![在这里插入图片描述][2021030822345098.gif_pic_center] -------------------- #### 什么是短路求值 #### 有些操作不需要处理整个流就能得到结果。例如,你需要对一个用 and 连起来的大布尔表达式进行求职,不管表达式有多长,只要有一个是false,那么就可以推断出整个表达式是false, **无需计算整个表达式,这就是短路**。 对于流而言,某些操作 (例如 allMatch 、 anyMatch 、 noneMatch 、 findFirst 和 findAny )不用处理整个流就能得到结果。只要找到一个元素,就可以有结果了 同样的,limit也是一个短路操作。 它只需要创建一个给?大小的流,而用不着处理流中所有的元素。在碰到无限大小的流的时?,这种操作就有用了:**它们可以把无限流变成有限流。** -------------------- ### 查找元素 findAny ### findAny 方法将返回当前流中的任意元素。它可以与其他流操作结合使用 举个例子:找到一道素菜。你可以结合使用 filter 和 findAny 方法来实现这个查询 /** * 需求: 找到一道素菜 */ public static Optional<Dish> randomVeDish(List<Dish> dishes) { return dishes.stream() .filter(Dish::isVegetarian) .findAny(); } 流水线将在后台进行优化使其只需走一遍,并在利用短路找到结果时立即结束。不过慢着代码里面的 Optional 是个什么玩意儿? `Optional<T>` 类( java.util.Optional )是一个容器类,代表一个值存在或不存在。在上面的代码中, findAny 可能什么元素都没找到。Java 8的库设计人员引入了 `Optional<T>` ,这样就不用返回容易出问题的 null 了。 几个常用的方法 * `isPresent()` 将在 Optional 包含值的时候返回 true , 否则返回 false 。 * `ifPresent(Consumer<T> block)` 会在值存在的时候执行给定的代码块。它让你传递一个接收 T 类型参数,并返回 void 的Lambda表达式。 * `T get()` 会在值存在时返回值,否则抛出一个 NoSuchElement 异常。 * `T orElse(T other)` 会在值存在时返回值,否则返回一个默认值。 ![在这里插入图片描述][20210308225803147.png] -------------------- ### 查找第一个元素 findFirst ### 有些流有一个出现顺序(encounter order)来指定流中项目出现的逻辑顺序(比如由 List 或排序好的数据列生成的流)。对于这种流,你可能想要找到第一个元素。为此有一个 findFirst方法,它的工作方式类似于 findany 。 例如,给定一个数字列表, 找出第一个平方能被3整除的数 /** * 需求: 给定一个数字列表, 找出第一个平方能被3整除的数 */ public static Optional<Integer> xxxx() { List<Integer> list = Arrays.asList(1,2,3,4,5,6); return list.stream() .map(x -> x *x) .filter(i -> i % 3 == 0) .findFirst(); } ### 何时使用 findFirst 和 findAny ### 什么会同时有 findFirst 和 findAny 呢?————–>并行。找到第一个元素在并行上限制更多。如果你不关心返回的元素是哪个, 使用 findAny ,因为它在使用并行流时限制较少。 ![在这里插入图片描述][20210308230144863.gif_pic_center] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70]: /images/20221023/16de386b9e454e5081bb5eb4c02240e3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 1]: /images/20221023/1a2aea7e62f04872a33011fd9303f09a.png [20210308115130430.png]: /images/20221023/89e2b9ac597d4aafb215a2dc5840697a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 2]: /images/20221023/8e48f7e8f9f44b6984ef27dc4175caf4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 3]: /images/20221023/30ed636812b148f4a159b980702f8494.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 4]: /images/20221023/dc5c64d20144486c8d2376598fa620db.png [20210308140321852.png]: /images/20221023/7fcf8afb9f89486ab59675c3914286e4.png [20210308140536397.gif_pic_center]: /images/20221023/103df10cb08a401cb9ea1047d5eefff4.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 5]: /images/20221023/6226c557a1cf4f76af5b602d6516993b.png [20210308163454436.png]: /images/20221023/062f2bb2129d4507b37a6c896f4abf02.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 6]: /images/20221023/6ba7263d8edb4f8286f98d5e8483071a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 7]: /images/20221023/92f92a8afb624e30b8d893d8732cdfdb.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 8]: /images/20221023/754320b9d21d4fe486017cccbc3b11f8.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 9]: /images/20221023/a215bc97b83b49909ea5cb7c3a6c32e5.png [20210308191941581.gif_pic_center]: /images/20221023/15e6bbafd63548208da63d0d238fb963.png [20210308220914350.jpg_pic_center]: /images/20221023/dff0a0e21da24b1190500d0dc4fad534.png [20210308195640101.gif_pic_center]: /images/20221023/03dfa90e05a141939f060b30ba6ee11c.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 10]: /images/20221023/7ee07a9c69584274a55c718149b6a493.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 11]: /images/20221023/08d0ed9650c946d0ace5fcdf4a92d07b.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 12]: /images/20221023/de19fd073e3148cc921584e66ba9bd8b.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 13]: /images/20221023/3a687d053620488c87647c942f57c8f3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdzaGFuZ3dlaQ_size_16_color_FFFFFF_t_70 14]: /images/20221023/bcbf7a388f714092af411326dff19aaf.png [2021030822345098.gif_pic_center]: /images/20221023/3738d1af375c40558ba86f2bfbc14a64.png [20210308225803147.png]: /images/20221023/0ca0011ecfc84805ae2837ecdaeec915.png [20210308230144863.gif_pic_center]: /images/20221023/b47477b224a74f0881bc5f1a64113db7.png
相关 Java 8新特性:流(Stream)操作 在Java 8中,引入了一种新的编程模型,那就是流(Stream)。流代表了数据处理的连续过程,可以让我们以更简洁、灵活的方式进行集合元素的操作。 流的基本操作包括: 1. 深碍√TFBOYSˉ_/ 2024年09月11日 08:06/ 0 赞/ 69 阅读
相关 Java 8新特性解读:Lambda表达式与流(Stream)操作 在Java 8中,引入了两个重要的新特性:Lambda表达式和流(Stream)操作。 1. Lambda表达式: Lambda表达式是Java 8简化匿名函数的一种方式。它 ゝ一纸荒年。/ 2024年09月04日 04:27/ 0 赞/ 66 阅读
相关 Java Stream 流解读 `java.util.Stream` 可以对元素列表进行一次或多次操作。Stream操作可以是中间值也可以是最终结果。最后的操作返回的是某种类型结果,而中间操作返回的是stre 我会带着你远行/ 2023年10月07日 21:30/ 0 赞/ 32 阅读
相关 Java 8 Stream流的常见操作 Stream流的使用 在 Java 8 中, 集合接口有两个方法来生成流: stream() − 为集合创建串行流。 parallelStre 客官°小女子只卖身不卖艺/ 2023年10月04日 20:29/ 0 赞/ 52 阅读
相关 Java 8 - Stream流骚操作解读 文章目录 分类 中间操作 终端操作 使用Stream流 筛选和切片 用谓词筛选 filter ゝ一世哀愁。/ 2022年11月06日 05:51/ 0 赞/ 212 阅读
相关 Java 8-Stream API-流操作 java.util.stream.Stream中的Stream接口定义了许多操作。它们可以分为两大类。 filter、map和limit可以连成一条流水线 col 约定不等于承诺〃/ 2022年05月21日 06:55/ 0 赞/ 258 阅读
相关 java8 stream流操作 Stream 在对流进行处理时,不同的流操作以级联的方式形成处理流水线。一个流水线由一个源(source),0 到多个中间操作(intermediate 我会带着你远行/ 2022年01月06日 16:39/ 0 赞/ 403 阅读
相关 java8 Stream流操作介绍 [https://blog.csdn.net/sf\_cyl/article/details/51900701][https_blog.csdn.net_sf_cyl_arti 快来打我*/ 2021年09月17日 08:36/ 0 赞/ 378 阅读
相关 Java8 Stream流操作 java8中的流式操作是一个很重要的内容 ![stream主要流操作][stream] 上图列出了stream主要流操作,我们可以看到,其实流操作可以类比我们的sql 桃扇骨/ 2021年06月10日 20:39/ 0 赞/ 572 阅读
还没有评论,来说两句吧...