Java流处理stream使用详解
作者:知奕奕 发布时间:2021-09-17 18:27:58
基本流
foreach 实现了外部迭代,它是建立于集合的基础上;
stream 流实现的是内部迭代
中间操作与终端操作
对任意集合使用 stream()
方法来使用流操作来对其进行内部迭代;
中间操作:流水线上的中间操作,他会返回一个 stream
终端操作:一般位于流水线末尾,输出一个非 stream 类型的值
这是下方代码的完整运行过程:
首先使用 stream 方法使用流来处理集合 names
使用过滤器 filter,过滤出字符串中含有字符 a 的字符串
distinct 进行去重
toList 将以上所有中间操作过后得到的结果进行汇总,转换成 list 并输出
public static void main(String[] args) {
List<String> strings = new ArrayList<>();
strings.add("asd");
strings.add("asd");
strings.add("qwe");
List<String> names = strings.stream()
// 过滤
.filter(d -> {
return d.contains("a");
})
// 去重
.distinct()
// 转换成列表
.toList();
for (String name : names) System.out.println(name); // 输出:asd
}
一些常见的终端操作
foreach
:消费流中所有元素并使用 lambda,该操作返回 void
count
:返回流中的元素个数,返回类型为 long
collect
:把流处理结果返回成一个集合,譬如 toList 方法
进阶流
筛选各异的元素
distinct 进行去重
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 4, 2, 2);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
}
截断
limit,做多返回前 n 个元素
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 4, 2, 2);
numbers.stream()
.limit(3)
.forEach(System.out::println);
}
跳过元素
skip(4) 表示跳过前四个元素,并返回后面所有的元素;
由于代码都差不多,这里不做过多演示
映射流
map
map 接收一个函数作为参数,他将对集合中的每个元素应用该函数,并返回该函数规定的值;
如下代码使用 map 获取了每个 dish 的名称并返回它,由此生成了由 dishname 构成的列表
public static void main(String[] args) {
List<Dish> dishes = new ArrayList<>();
dishes.add(new Dish("apple", true, 120, Dish.Type.FRUIT));
dishes.add(new Dish("pork", false, 900, Dish.Type.MEAT));
dishes.add(new Dish("fish", false, 400, Dish.Type.FISH));
List<String> dishNames = dishes.stream()
.map(Dish::getName)
.toList();
dishes.forEach(System.out::println);
}
flatMap
map 是将每个元素都映射成了一个流;
flatMap 是将每个元素都放如同一个流中!
以下代码实现:提取单词表中出现的单词;
Arrays.stream
可以将集合转换成流的形式;
应当首先应用 map,将元素进行映射后,在使用 flatMap 把这些映射完毕的元素全部装入一个统一的流里面!
public static void main(String[] args) {
// 创建单词表
String[] words = {"goodbye", "hello", "night"};
// 将单词表转换成流的形式
Stream<String> swords = Arrays.stream(words);
// 首先使用map,将所有字母都一一分割来开
List<String> strings = swords.map(word -> word.split(""))
// 使用扁平map,将提取到的字母装入一个流中
.flatMap(Arrays::stream)
// 字母去重
.distinct()
// 转换成列表
.toList();
strings.forEach(System.out::println);
}
匹配
anyMatch 能应答:流中是否有至少有一个元素能匹配所给定的谓词(方法引用)
public static void main(String[] args) {
List<Dish> dishes = Menu.getMenu();
if(dishes.stream().anyMatch(Dish::isVegetarian)){
System.out.println("至少有一个素菜!");
}
}
全匹配与非全匹配
allMatch 方法检查谓词能否匹配所有元素;
noneMatch 方法作用与 allMatch 方法完全相反;
Optional
findAny
findAny
方法默认返回一个 Optional<T>
ifPresent 会在值存在的时候执行后面的 lambda 函数
public static void main(String[] args) {
List<Dish> dishes = Menu.getMenu();
dishes.stream()
.filter(Dish::isVegetarian)
.findAny()
.ifPresent(d -> System.out.println(d.getName()));
}
findFirst
顾名思义,找到集合中的第一个元素
归约
求和
下方展示了三种求和方式:
直接使用 arrays 函数自带的 sum 方法求和;
使用 reduce,参数一表示初始值,参数二为对值的操作
同样使用 reduce,但是引入了谓词!
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5};
int sum = Arrays.stream(nums).sum();
int sum2 = Arrays.stream(nums)
.reduce(0, (a, b) -> a + b);
int sum3 = Arrays.stream(nums)
.reduce(0, Integer::sum);
}
归约相关阐发
map+reduce 常被作为一种形式来进行并行化;
使用 reduce 进行的迭代被内部抽象化掉了,所以有益于并行的执行;
parallelStream 可以方便的进行并行操作,但是也带来了同步不安全的隐患;
数值流
使用 mapToInt 返回特化的 IntStream
public static void main(String[] args) {
List<Dish> dishes = Menu.getMenu();
int sum = dishes.stream()
.mapToInt(Dish::getCalories)
.sum();
}
boxed
将某个特化流转换成一般流,可以使用 boxed 方法
IntStream is = dishes.stream().mapToInt(Dish::getCalories);
Stream<Integer> sis = is.boxed();
range
针对特化流 IntStream 和 LongStream,他们均有 range 和 rangeClose 方法;
range:遍历范围内所有数字除了右边界数字
rangeClose:遍历包含右边界的所有范围数字
下面代码展示了获取 1-100 内所有偶数的个数
IntStream evenNumbers = IntStream.rangeClosed(1,100)
.filter(n->n%2==0);
System.out.println(evenNumbers.count());
构建流
创建流的三种方式
Stream.of(xxx) 通过数值直接构建;
Arrays.stream() 数组创建;
File.lines() 通过获取的文件内容创建;
来源:https://blog.csdn.net/delete_you/article/details/127157037
猜你喜欢
- JACOB的方法,足可以解决这个问题,但是我既然以前曾经做过报表,就想尝试不同的方法。JACOB是一座连接JAVA和微软的桥,所有的解析由微
- spring @Autowired注解无法注入问题简述在使用spring框架的过程中,常会遇到这种两情况:1、在扫描的包以外使用需要使用ma
- 一.前言这一篇来看看 SpringIOC 里面的一个细节点 , 来简单看看 BeanDefinition 这个对象 , 以及有没有办法对其进
- spring.thymeleaf.cache=false不起作用配置是清除缓存,实现热部署。也就是修改了html后不用重启,刷新页面就能看到
- Map集合的概述概述:interface Map<K,V> 其中K是键的类型,键是唯一的,不重复。V是值的类型,是可以重复。且每
- IDEA安装后找不到.vmoptions文件在安装IDEA后在C盘的C:\Users\你的电脑用户名.IntelliJIdea2019.1\
- 需求:有些时候,我们需要连接多个数据库,但是,在方法调用前并不知道到底是调用哪个。即同时保持多个数据库的连接,在方法中根据传入的参数来确定。
- 前言在 Java 中,跳转的实现方式有两种:请求转发和请求重定向,但二者是完全不同的,所以我们今天就来盘它。请求转发和请求重定向主要区别,包
- HashMap的get()方法的NullPointerException今天写代码发现一个 bug,HashMap的 get() 方法一直报
- 1.mkString()方法的使用:mkString(seq:String)方法是将原字符串使用特定的字符串seq分割。mkString(s
- 一、Java后端使用MultipartFile@PostMapping(value = "/upload")  
- Logback 背景Logback是由log4j创始人设计的另一个开源日志组件,官方网站:http://logback.qos.ch。它当前
- 学过Spring的小伙伴对于IOC一定不陌生,IOC:控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向
- 多线程的创建,方式一:继承于Thread类1.创建一个继承于Thread类的子类2.重写Thread类的run()--->将此线程执行
- 前言代码生成器,也叫逆向工程,是根据数据库里的表结构,自动生成对应的实体类、映射文件和接口。看到很多小伙伴在为数据库生成实体类发愁,现分享给
- Java 使用getClass().getResourceAsStream()方法获取资源之前想获取一个资源文件做一些处理,使用getCla
- 1、认识XML解析技术1.1、XML相关概念(1)DTD:XML语法规则,是XML文件的验证机制,可以通过比较XML文档和DTD文件看文档是
- 使用poi生成excel通常包含一下几个步骤创建一个工作簿创建一个sheet创建一个Row对象创建一个cell对象(1个row+1个cell
- Java连接SQL Server数据库的详细操作流程一.明确JDK版本和下载驱动1.1 JDK版本查看win + r输入cmd,命令窗口输入
- 今天给大家介绍一下SpringBoot中JPA的一些常用操作,例如:增删改查、分页、排序、事务操作等功能。下面先来介绍一下JPA中一些常用的