一.什么是stream?

1.概述

Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。

简单描述一下大概是这样:

二. 举个例子?

现在有一个字符串集合,我们需要过滤掉集合里头长度小于2的字符串:

public static void main( String[] args ) {
List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
List<String> stringList = new ArrayList<>();
for (String str : strings){
//如果长度大于2
if (str.length() >= 2){
//将字符串添加至新集合
stringList.add(str);
}
}
strings = stringList;
}

如果使用stream实现一模一样的效果:

public static void main( String[] args ) {
List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
//通过stream操作集合
strings = strings.stream()
//去掉长度小于2的字符串
.filter(s -> s.length() >= 2)
//转回集合
.collect(Collectors.toList());
}

可见,使用streamAPI可以轻松写出更高效,更简洁,可读性更强的代码

三. 如何使用stream?

简单的说,分两步:生成流,操作流

1. 生成流

Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, 不支持Map

1.1 Collection接口的stream()或parallelStream()方法

//将Set或List集合直接转换为stream对象
List<Person> personList = new ArrayList<>();
Set<Person> set = new HashSet<>(); Stream<Person> personStream1 = personList.stream();//生成串行流
Stream<Person> personStream2 = set.parallelStream();//生成并行流

1.2 Stream.of(),Arrays.stream,Stream.empty()方法

String[] strArr = {"a","a","a","a","a","a"};

//Stream.empty()
Stream<Integer> integerStream = Stream.empty(); //Stream.of() (方法内部调用的还是Arrays.stream)
Stream<String> stringStream = Stream.of(strArr); //Arrays.stream
Stream<String> stringStream2 = Arrays.stream(strArr);

1.3 Stream.concat()方法

//已有的对象
Stream<Integer> integerStream = Stream.empty();
Stream<String> stringStream = Stream.of(strArr);
Stream<String> stringStream2 = Arrays.stream(strArr); //合并两个流
Stream conStream1 = Stream.concat(stringStream,integerStream);
Stream conStream2 = Stream.concat(stringStream,stringStream2);

1.4 静态的Files.lines(path)

File file = new File("D://test.txt");
Stream<String> lines = Files.lines(file);

2. 操作流

Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以在后头跟上其他中间操作

//接下来的示例代码基于此集合
List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");

2.1 filter(Predicate:将结果为false的元素过滤掉

//去掉长度小于2的字符串
strings = strings.stream()
.filter(s -> s.length() >= 2)
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings
[ab, bc, cd, abcd, jkl]

2.2 map(fun):转换元素的值,可以引用方法或者直接用lambda表达式

strings = strings.stream()
//为每个字符串加上“???”
.map(s -> s += "???")
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings
[ab???, ???, bc???, cd???, abcd???, ???, jkl???]

2.3 limit(n):保留前n个元素

strings = strings.stream()
//保留前3个
.limit(3)
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings
[ab, , bc]

2.4 skip(n):跳过前n个元素

strings = strings.stream()
//跳过前2个
.skip(2)
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings
[bc, cd, abcd, , jkl]

2.5 distinct():剔除重复元素

strings = strings.stream()
//过滤重复元素
.distinct()
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings(过滤掉了一个空字符串)
[ab, , bc, cd, abcd, jkl]

2.6 sorted():通过Comparable对元素排序

strings = strings.stream()
//按字符串长度排序
.sorted(
//比较字符串长度
Comparator.comparing(s -> s.length())
)
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings(过滤掉了一个空字符串)
[, , ab, bc, cd, jkl, abcd]

2.7 peek(fun):流不变,但会把每个元素传入fun执行,可以用作调试

strings = strings.stream()
//为字符串增加“???”
.peek(s -> s += "???")
//返回集合
.collect(Collectors.toList()); System.out.println(strings); //打印strings,和map对比,实际并没有改变集合
[ab, , bc, cd, abcd, , jkl]

2.8 flatMap(fun):若元素是流,将流摊平为正常元素,再进行元素转换

//将具有多重嵌套结构的集合扁平化

//获取一个两重集合
List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
List<String> strings2 = Arrays.asList("asd", "", "bzxasdc", "cddsdsd", "adsdsg","", "jvcbl");
List<List<String>> lists = new ArrayList<>();
lists.add(strings);
lists.add(strings2); //获取将两重集合压成一层
List<String> stringList = lists.stream()
//将两重集合的子元素,即集合strings和strings2转成流再平摊
.flatMap(Collection::stream)
//返回集合
.collect(Collectors.toList()); System.out.println(stringList); //打印stringList
[ab, , bc, cd, abcd, , jkl, asd, , bzxasdc, cddsdsd, adsdsg, , jvcbl]

2.9 anyMatch(fun),allMatch(fun):判断流中的元素是否匹配 【最终操作】

//allMatch
Boolean isAllMatch = strings.stream()
//判断元素中是否有匹配“ab”的字符串,返回true或fals
//判断元素中的字符串是否都与“ab”匹配,返回true或fals
.allMatch(str -> str.equals("ab")); System.out.println(isMatch); //anyMatch
Boolean isAnyMatch = strings.stream()
//判断元素中是否有匹配“ab”的字符串,返回true或fals
.anyMatch(str -> str.equals("ab")); System.out.println("isAnyMatch:" + isAnyMatch);
System.out.println("isAllMatch:" + isAllMatch); //打印结果
isAnyMatch:true
isAllMatch:false

2.10 forEach(fun): 迭代流中的每个数据 【最终操作】

strings.stream()
//遍历每一个元素
.forEach(s -> System.out.print(s + "; "));

2.11 collect():返回结果集 【最终操作】

strings = strings.stream()
//返回集合
.collect(Collectors.toList());

四. 使用IntSummaryStatistics类处理数据

1. IntSummaryStatistics类

IntSummaryStatistics类,在 java8中配合Stream使用,是用于收集统计信息(例如计数,最小值,最大值,总和和*平均值)的状态对象。

这个类长这样:

public class IntSummaryStatistics implements IntConsumer {
private long count;
private long sum;
private int min = Integer.MAX_VALUE;
private int max = Integer.MIN_VALUE; public IntSummaryStatistics() { } @Override
public void accept(int value) {
++count;
sum += value;
min = Math.min(min, value);
max = Math.max(max, value);
} public void combine(IntSummaryStatistics other) {
count += other.count;
sum += other.sum;
min = Math.min(min, other.min);
max = Math.max(max, other.max);
} public final long getCount() {
return count;
} public final long getSum() {
return sum;
} public final int getMin() {
return min;
} public final int getMax() {
return max;
} public final double getAverage() {
return getCount() > 0 ? (double) getSum() / getCount() : 0.0d;
} @Override
public String toString() {
return String.format(
"%s{count=%d, sum=%d, min=%d, average=%f, max=%d}",
this.getClass().getSimpleName(),
getCount(),
getSum(),
getMin(),
getAverage(),
getMax());
}
}

2.使用

这个类的理解起来很简单,内部有这几个方法:

2.1 获取总条数:getCount(),

2.2 获取和:getSum(),

2.3 获取最小值:getMin(),

2.4 获取最大值:getMax(),

2.5 获取平均值:getAverage()

示例如下:

public static void main( String[] args ) {
List<Integer> integerList = Arrays.asList(3, 4, 22, 31, 75, 32, 54); IntSummaryStatistics sta = integerList
.stream()
//将元素映射为对应的数据类型(int,double,long)
.mapToInt(i -> i)
//转换为summaryStatistics类
.summaryStatistics(); System.out.println("总共有 : "+ sta.getCount());
System.out.println("列表中最大的数 : " + sta.getMax());
System.out.println("列表中最小的数 : " + sta.getMin());
System.out.println("所有数之和 : " + sta.getSum());
System.out.println("平均数 : " + sta.getAverage());
} //打印结果
总共有 : 7
列表中最大的数 : 75
列表中最小的数 : 3
所有数之和 : 221
平均数 : 31.571428571428573

JDK1.8新特性(一):stream的更多相关文章

  1. JDK1.8新特性之Stream类初识

    JDK1.8新特性之Stream类初识 import java.util.Arrays; import java.util.List; import java.util.Optional; impor ...

  2. jdk1.8 新特性之Stream

    --------------------- 作者:码农农码一生 来源:CSDN 原文:https://blog.csdn.net/chenhao_c_h/article/details/8069128 ...

  3. JDK1.8新特性——Stream API

    JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...

  4. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  5. JDK1.8 新特性

    jdk1.8新特性知识点: Lambda表达式 函数式接口 *方法引用和构造器调用 Stream API 接口中的默认方法和静态方法 新时间日期API https://blog.csdn.net/qq ...

  6. jdk1.8新特性应用之Iterable

    我们继续看lambda表达式的应用: public void urlExcuAspect(RpcController controller, Message request, RpcCallback ...

  7. JDK1.8新特性——Collector接口和Collectors工具类

    JDK1.8新特性——Collector接口和Collectors工具类 摘要:本文主要学习了在Java1.8中新增的Collector接口和Collectors工具类,以及使用它们在处理集合时的改进 ...

  8. JDK1.8新特性之(三)--函数式接口

    在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...

  9. JDK1.8新特性之(一)--Lambda表达式

    近期由于新冠疫情的原因,不能出去游玩,只能在家呆着.于是闲来无事,开始阅读JDK1.8的源代码.在开始之前也查询了以下JDK1.8的新特性,有针对性的开始了这段旅程. 只看不操作,也是不能心领神会的. ...

  10. JDK1.8新特性之(二)--方法引用

    在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...

随机推荐

  1. 一个基于Net Core3.0的WPF框架Hello World实例

    目录 一个基于Net Core3.0的WPF框架Hello World实例 1.创建WPF解决方案 1.1 创建Net Core版本的WPF工程 1.2 指定项目名称,路径,解决方案名称 2. 依赖库 ...

  2. python pytesseract使用

    正确使用方法 1.tesseract-orc安装 tesseract-ocr-setup-3.05.00dev.exe下载 2.pytesseract pip install pytesseract ...

  3. 学习笔记48_Memcache跟用户登录模块结合

    public interface ICacheWriter {  void AddCache(string key,object value, DateTime expDate);  void Add ...

  4. [Scala]Scala安装以及在IDEA中配置Scala

    一  Scala简述 Scala (斯卡拉)是一门多范式(multi-paradigm)的编程语言. 这里所谓的范式,指的是编写程序的方式,不同的编程语言,方式也不尽相同,也就意味着Scala编程语言 ...

  5. Spring Cloud Gateway使用简介

    Spring Cloud Gateway是类似Nginx的网关路由代理,有替代原来Spring cloud zuul之意: Spring 5 推出了自己的Spring Cloud Gateway,支持 ...

  6. 【PyTorch教程】P3. Python学习中的两大法宝函数(当然也可以用在PyTorch)

    温馨提示:为了更好的教程体验,提供视频.阅读地址 Youtube: https://www.youtube.com/playlist?list=PLgAyVnrNJ96CqYdjZ8v9YjQvCBc ...

  7. html5 微信真机调试方法vConsole

    html5 微信真机调试方法 vConsolehttps://blog.csdn.net/weixin_36934930/article/details/79870240

  8. [多态] java笔记之多态性

    1.多态,说的是对象,说的不是类. 2. 3.多态 = polymorphism 4. 调用如下: 5. 6.口诀: 7.对象的向上转型: 8.对象的向下转型: 9.下面这个异常叫做ClassCast ...

  9. 这份最新Python面试精选问题你会几道?

    相信很多小伙伴学python以后都想进大厂,但是进大厂前你得了解些大厂面试题,可以在面试前复习下,以下是精选的5道python面试题: 第一. Python 的特点和优点是什么? Python 可以作 ...

  10. 通过 position:fixed 实现底部导航

    通过 position:fixed 实现底部导航 HTML <div id="footer">页脚</div> CSS #footer { clear: b ...