Java8新特性之Stream流
什么是Stream流
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。 是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
Stream特点
- 无存储。Stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
- 为函数式编程而生。对Stream的任何修改都不会修改背后的数据源,比如对Stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新Stream。
- 惰式执行。Stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
- 可消费性。Stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
Stream流操作
1: 创建Stream
主要负责新建一个Stream流,或者基于现有的数组、List、Set、Map等集合类型对象创建出新的Stream流。
API | 功能说明 |
---|---|
stream() | 创建出一个新的stream串行流对象 |
parallelStream() | 创建出一个可并行执行的stream流对象 |
Stream.of() | 通过给定的一系列元素创建一个新的Stream串行流对象 |
示例
/**
* 通过集合生成,应用中最常用的一种
*/
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream1 = integerList.stream();
/**
* 通过数组生成
*/
int[] intArr = new int[]{1, 2, 3, 4, 5};
IntStream stream2 = Arrays.stream(intArr);
/**
* 创建并行流对象
*/
Stream<Integer> promotionStream = integerList.parallelStream();
2: 中间管道
负责对Stream进行处理操作,并返回一个新的Stream对象,中间管道操作可以进行叠加
API | 功能说明 |
---|---|
filter() | 按照条件过滤符合要求的元素, 返回新的stream流 |
map() | 将已有元素转换为另一个对象类型,一对一逻辑,返回新的stream流 |
flatMap() | 将已有元素转换为另一个对象类型,一对多逻辑,即原来一个元素对象可能会转换为1个或者多个新类型的元素,返回新的stream流 |
limit() | 仅保留集合前面指定个数的元素,返回新的stream流。limit的参数值必须>=0,否则将会抛出异常 |
skip() | 跳过集合前面指定个数的元素,返回新的stream流。skip的参数值必须>=0,否则将会抛出异常 |
concat() | 将两个流的数据合并起来为1个新的流,返回新的stream流 |
distinct() | 对Stream中所有元素进行去重,返回新的stream流 |
sorted() | 对stream中所有的元素按照指定规则进行排序,返回新的stream流 |
peek() | 对stream流中的每个元素进行逐个遍历处理,返回处理后的stream流 |
示例:
filter()
/**
* filter筛选
* 通过使用filter方法进行条件筛选,filter的方法参数为一个条件
*/
List<Integer> integerList = Arrays.asList(1, 1, 2, 3, 4, 5);
Stream<Integer> stream = integerList.stream().filter(i -> i > 3);
map()
主要用于List
/**
* map流映射(所谓流映射就是将接受的元素映射成另外一个元素)
*/
List<String> stringList = Arrays.asList("str1", "str2", "str3", "str5");
Stream<Integer> streams = stringList.stream().map(String::hashCode);
flatMap()
将已有元素转换为另一个对象类型,一对多逻辑
/**
* flatMap流转换(将一个流中的每个值都转换为另一个流)
*/
List<String> wordList = Arrays.asList("Hello", "World");
List<String> strList = wordList.stream()
.map(w -> w.split("r"))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
limit()
/**
* limit返回指定流个数
* 通过limit方法指定返回流的个数,limit的参数值必须>=0,否则将会抛出异常
*/
List<String> wordList = Arrays.asList("Hello", "World","!");
Stream<String> limitStream = wordList.stream().limit(1);
skip()
/**
* skip跳过流中的元素
* 通过skip方法跳过流中的元素,例子中打印出来的数据: World,! 。skip的参数值必须>=0,否则将会抛出异常
*/
List<String> wordList = Arrays.asList("Hello", "World","!");
Stream<String> limitStream = wordList.stream().skip(1);
concat()
Stream<String> streamOne = Stream.of("Hello");
Stream<String> streamTwo = Stream.of("World");
Stream<String> concatStream = Stream.concat(streamOne, streamTwo);
distinct()
/**
* distinct主要用来去重,以下代码片段使用 distinct 对元素进行去重
*/
List<String> wordList = Arrays.asList("Hello", "World","!","Hello","!");
Stream<String> limitStream = wordList.stream().distinct();
sorted()
/**
* sorted对流进行排序
* sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法进行排序
*/
List<Integer> integerList = Arrays.asList(1, 3,2,10,7);
Stream<Integer> sortedStream = integerList.stream().sorted();
/**
* 通过比较器比较
*/
List<String> wordList = Arrays.asList("Hello", "World","!","Hello","!");
wordList.stream().sorted(((str1, str2) -> {
if (str1.length()> str2.length()) {
return -1;
} else {
return 1;
}
}));
peek()
/**
* peek()属于中间方法,没有结束
* peek只能作为管道中途的一个处理步骤,而没法直接执行得到结果,其后面必须还要有其它终止操作的时候才会被执行
*/
List<String> wordList = Arrays.asList("Hello World!");
//没有输出
wordList.stream().peek(sentence -> System.out.println(sentence));
//输出结果
wordList.stream().peek(sentence -> System.out.println(sentence)).count();
3: 终止管道
通过终止管道操作之后,Stream流将会结束,最后可能会执行某些逻辑处理,或者是按照要求返回某些执行后的结果数据
API | 功能说明 |
---|---|
count() | 返回stream处理后最终的元素个数 |
max() | 返回stream处理后的元素最大值 |
min() | 返回stream处理后的元素最小值 |
findFirst() | 找到第一个符合条件的元素时则终止流处理 |
findAny() | 找到任何一个符合条件的元素时则退出流处理,这个对于串行流时与findFirst相同,对于并行流时比较高效,任何分片中找到都会终止后续计算逻辑 |
anyMatch() | 返回一个boolean值,类似于isContains(),用于判断是否有符合条件的元素 |
allMatch() | 返回一个boolean值,用于判断是否所有元素都符合条件 |
noneMatch() | 返回一个boolean值, 用于判断是否所有元素都不符合条件 |
collect() | 将流转换为指定的类型,通过Collectors进行指定 |
toArray() | 将流转换为数组 |
iterator() | 将流转换为Iterator对象 |
foreach() | 无返回值,对元素进行逐个遍历,然后执行给定的处理逻辑 |
count()
count用来统计流中的元素个数。
/**
* 统计流中元素个数
* 通过使用count方法统计出流中元素个数
*/
List<String> wordList = Arrays.asList("Hello","World","!!");
long count = wordList.stream().count();
max()/min()
获取流中最小最大值
List<Integer> integerList = Arrays.asList(100,111,22,3,343);
Optional<Integer> min = integerList.stream().min(Integer::compareTo);
Optional<Integer> max = integerList.stream().max(Integer::compareTo);
findFirst()
查找大于100的第一个值
/**
* 查询列表中大于100的数值
*/
List<Integer> integerList = Arrays.asList(100,111,22,3,343);
Optional<Integer> result = integerList.stream().filter(v -> v > 100).findFirst();
findAny()
找到任何一个符合条件的元素时则退出流处理
List<Integer> integerList = Arrays.asList(100,343,22,3,111);
Optional<Integer> result = integerList.stream().filter(v -> v > 100).findAny();
System.out.println(result.get());
anyMatch()
/**
* 查询列表中是否包含111的字符串
*/
List<String> integerList = Arrays.asList("100", "343","22","3","111");
boolean b = integerList.stream().anyMatch("111"::equals);
allMatch()
这个和anyMatch() 的类似,列表里面的元素都要匹配上。
noneMatch()
这个和anyMatch() 的类似,列表里面的元素都不能匹配上。
剩下的都是一些比较简单的,这里不在进行举例了。
优势和劣势
相对于foreach的方式,Stream有很多优势:
- 代码简洁,逻辑清洗。
- 函数式接口,延迟执行的特性,中间管道操作不管有多少步骤都不会立即执行,只有遇到终止操作的时候才会开始执行,可以避免一些中间不必要的操作消耗
- 并行流场景效率会比迭代器逐个循环更高
劣势:
- 代码调试不是很方便
- 开发者需要去适应这种模式
以上就是本篇文章的所有内容,请大家多多指教。
标签:Java,Stream,stream,Arrays,integerList,元素,List,特性 From: https://www.cnblogs.com/zwhdd/p/17448911.html