热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java8Stream流Intermediate中间操作详细解析

Stream的操作中有中间操作和终端操作,顾名思义,中间操作就是对stream流的一些操作,操作对象时stream本身,终端操作既是对流的处理结

Stream的操作中有中间操作和终端操作,顾名思义,中间操作就是对stream流的一些操作,操作对象时stream本身,终端操作既是对流的处理结果,为了直观的了解,我们看下接口定义:

public interface Stream<T> extends BaseStream<T, Stream<T>> {Stream<T> filter(Predicate<? super T> predicate);<R> Stream<R> map(Function<? super T, ? extends R> mapper);IntStream mapToInt(ToIntFunction<? super T> mapper);LongStream mapToLong(ToLongFunction<? super T> mapper);DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);Stream<T> distinct();Stream<T> sorted();Stream<T> sorted(Comparator<? super T> comparator);Stream<T> peek(Consumer<? super T> action);Stream<T> limit(long maxSize);Stream<T> skip(long n);void forEach(Consumer<? super T> action);void forEachOrdered(Consumer<? super T> action);Object[] toArray();<A> A[] toArray(IntFunction<A[]> generator);T reduce(T identity, BinaryOperator<T> accumulator);Optional<T> reduce(BinaryOperator<T> accumulator);<U> U reduce(U identity,BiFunction<U, ? super T, U>accumulator,
BinaryOperator<U> combiner);<R> R collect(Supplier<R> supplier,iConsumer<R, ? super T> accumulator,iConsumer<R, R> combiner);<R, A> R collect(Collector<? super T, A, R> collector);Optional<T> min(Comparator<? super T> comparator);Optional<T> max(Comparator<? super T> comparator);long count();boolean anyMatch(Predicate<? super T> predicate);boolean allMatch(Predicate<? super T> predicate);boolean noneMatch(Predicate<? super T> predicate);Optional<T> findFirst();Optional<T> findAny();public static<T> Builder<T> builder() {return new Streams.StreamBuilderImpl<>();}public static<T> Stream<T> empty() {return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);}public static<T> Stream<T> of(T t) {return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);}public static<T> Stream<T> of(T... values) {return Arrays.stream(values);}
}

对于返回值为** 接口本身的Stream ** 或者返回 其他对象类型的&#xff0c;返回接口类型的我们都可认为是中间操作&#xff0c;返回 其他具体类型的为终端操作。
下面我们来具体看每个方法&#xff1a;
1、filter(Predicate) 将结果为false的元素过滤掉

&#64;Test
public void testFilter(){Stream<Integer> stream &#61; Stream.of(1, 2, 3);stream.filter(e->e > 2).forEach(System.out::println);// 符合大于2的数字 -> 3
}

filter() 传入需要过滤的条件
2、map(fun) 转换元素的值&#xff0c;可以用方法引元或者lambda表达式

&#64;Test
public void testMap(){Stream<Integer> stream &#61; Stream.of(1, 2, 3);stream.map(o -> Integer.toString(o)).forEach(s->{System.out.println(s);// 1,2,3System.out.println(s.getClass());// class java.lang.String});List<Dish> dishes &#61; Arrays.asList(new Dish("beef", "100", 200, Dish.Type.MEAT),new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("rice", "true", 350, Dish.Type.OTHER));dishes.stream().map(Dish::getName).forEach(System.out::println);// beef pork rice
}

可以看到&#xff0c;使用map方法实现了Integer-> String的类型转换&#xff0c;也可以获取对象的某一属性值等等。
3、flatMap(fun) 若元素是流&#xff0c;将流摊平为正常元素&#xff0c;再进行元素转换

String [] arr &#61; {"aaa","bbb","ccc"};
Arrays.stream(arr).map(s-> s.split("")).forEach(System.out::println);// [Ljava.lang.String;&#64;33e5ccce
List<String[]> collect &#61; Arrays.stream(arr).map(s -> s.split("")).collect(Collectors.toList());

我们可以看到使用map时输出的是一个地址&#xff0c;返回的类型实际是 List 使用flatMap时

List<String> list &#61; Arrays.stream(arr).map(s -> s.split("")).flatMap(Arrays::stream).collect(Collectors.toList());
Arrays.stream(arr).map(s->s.split("")).flatMap(Arrays::stream).forEach(System.out::println);// aaabbbccc

可以看到返回的类型为List &#xff0c;将整个外层list包含的所有元素放到一个层面处理。
4、limit(n) 保留前n个元素

List<Dish> mean &#61; Arrays.asList(new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("beef", "false", 700, Dish.Type.MEAT),new Dish("chicken", "false", 400, Dish.Type.MEAT),new Dish("french fries", "true", 530, Dish.Type.OTHER),new Dish("rice", "true", 350, Dish.Type.OTHER),new Dish("season fruit", "true", 120, Dish.Type.OTHER),new Dish("pizza", "true", 550, Dish.Type.OTHER),new Dish("prawns", "false", 300, Dish.Type.FISH),new Dish("salmon", "false", 450, Dish.Type.FISH)
);
//截取前2个菜品
List<Dish> dishes &#61; mean.stream().limit(2).collect(Collectors.toList());
System.out.println(dishes.size());//2
mean.stream().limit(2).forEach(System.out::println);
//Dish{name&#61;&#39;pork&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;800, type&#61;MEAT}
//Dish{name&#61;&#39;beef&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;700, type&#61;MEAT}

5、skip(n) 跳过前n个元素

// 跳过前7个菜品
mean.stream().skip(7).forEach(System.out::println);
//Dish{name&#61;&#39;prawns&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;300, type&#61;FISH}
//Dish{name&#61;&#39;salmon&#39;, vegetarian&#61;&#39;false&#39;, calories&#61;450, type&#61;FISH}

对于limit 和 skip 配合使用可以实现分页操作
**6、distinct() 去重 剔除重复元素 **

&#64;Test
public void testDistinct(){int[] arr &#61; {1,1,2,2,3,4,5};Arrays.stream(arr).distinct().forEach(System.out::println);// 1 2 3 4 5
}

7、sorted() 排序 默认升序

int[] arr &#61; {5,7,3,1,8,4};
Arrays.stream(arr).sorted().forEach(System.out::println);// 134578

8、sorted(Comparator) 按传入的条件排序

List<Dish> mean &#61; Arrays.asList(new Dish("pork", "false", 800, Dish.Type.MEAT),new Dish("beef", "false", 700, Dish.Type.MEAT),new Dish("chicken", "false", 400, Dish.Type.MEAT),new Dish("french fries", "true", 530, Dish.Type.OTHER),new Dish("rice", "true", 350, Dish.Type.OTHER),new Dish("season fruit", "true", 120, Dish.Type.OTHER),new Dish("pizza", "true", 550, Dish.Type.OTHER),new Dish("prawns", "false", 300, Dish.Type.FISH),new Dish("salmon", "false", 450, Dish.Type.FISH)
);
// 按菜品的卡路里排序 并打印卡路里的值
mean.stream().sorted(Comparator.comparing(Dish::getCalories)).map(Dish::getCalories).forEach(System.out::println);//120 300 350 400 450 530 550 700 800
// reversed 反转 实现倒叙排序
mean.stream().sorted(Comparator.comparing(Dish::getCalories).reversed()).map(Dish::getCalories).forEach(System.out::println);// 800 700 550 530 450 400 350 300 120

9、peek(fun) 流不变 接收一个没有返回值的λ表达式&#xff0c;可以做一些输出&#xff0c;外部处理

&#64;Test
public void testPeek(){int [] arr &#61; {1,1,2,3,4,4,5};Arrays.stream(arr).distinct().map(o-> o*2).peek(s->System.out.println("peek 做一些输出操作"&#43;s)).forEach(System.out::println);
}

peek 和 map 的区别
peek 的定义

Stream<T> peek(Consumer<? super T> action);

熟悉lambda的都知道Consumer的实现类 应该只有一个方法&#xff0c;该方法返回类型为void。

Consumer<Integer> c &#61; i -> System.out.println("hello" &#43; i);

map的定义

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

我们发现Function 比 Consumer 多了一个 return。 map接收一个有返回值的lambda表达式&#xff0c;之后Stream的泛型类型将转换为map参数λ表达式返回的类型

Function<Integer,String> f &#61; x -> {return "hello" &#43; i;};


推荐阅读
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • 简述在某个项目中需要分析PHP代码,分离出对应的函数调用(以及源代码对应的位置)。虽然这使用正则也可以实现,但无论从效率还是代码复杂度方面考虑ÿ ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
  • 本文介绍了如何使用OpenXML按页码访问文档内容,以及在处理分页符和XML元素时的一些挑战。同时,还讨论了基于页面的引用框架的局限性和超越基于页面的引用框架的方法。最后,给出了一个使用C#的示例代码来按页码访问OpenXML内容的方法。 ... [详细]
  • 在加载一个第三方厂商的dll文件时,提示“找不到指定模块,加载失败”。由于缺乏必要的技术支持,百思不得期间。后来发现一个有用的工具 ... [详细]
author-avatar
思念如此难受_351
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有