Stream 流是 Java 8 提供给开发者一套新的处理集合的API,他把我们将要处理的集合作为流,就像流水线一样,我们可以对其中的元素进行筛选,过滤,排序等中间操作,只不过这种操作更加简洁高效。

Stream的创建:
  • 1.可以通过Collection系列的集合提供的stream()或者parallelStream()方法,集合的stream方法创建的是串行流,parallelStream方法创建的是并行流(并行流就是多线程进行操作,这个时候就要考虑线程安全问题了)
  • 2.可以通过Arrays.stream()获取数组流
  • 3.通过Stream类中的静态方法of()可以创建流对象
  • 当创建一个无限流使用Stream.iterate()方法,是一个死循环

//Stream 的创建


//1.通过集合的stream()方法创建串行流
ArrayList<Object> list = new ArrayList<>();
Stream<Object> stream = list.stream();
//2.也可以通过集合的parallelStream创建并行流
Stream<Object> parallelStream = list.parallelStream();
//3.通过Arrays.stream(T[] t),将数组转换成流
IntStream stream1 = Arrays.stream(new int[10]);
//4.通过Stream的静态方法of创建流
Stream<String> stringStream = Stream.of("aaa", "bbb", "ddd", "ccc"); //创建无限流 迭代
Stream<Integer> iterate = Stream.iterate(1, (x) -> x + 2);
iterate.limit(10).forEach(System.out::println);//生成奇数从一开始往后的10位 //生成
Stream.generate(()->(int)(Math.random()*100))//随机生成10个100以内的int类型数
.limit(10)
.forEach(System.out::println);
Stream的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线线上触发终止操作,否则中间操作就不会执行任何处理,并不会显示处理结果。而在终止操作时一次性全部处理,称为惰性求值。

  • 筛选与切片

filter-接收Lambda,从流中排除某些元素
limit–截断流,使其元素不超过给定数量
skip(n) – 跳过元素,返回一个扔掉了前n个元素的流。若流中的元素个数小于n,则返回null,与limit()互补
distinct–筛选通过流所生成元素的hashCode(),equals()方法来去掉重复的元素

public class StreamAPITest {
List<Employee> employees = Arrays.asList(
new Employee("小明", 12000, 32),
new Employee("小红", 8000, 23),
new Employee("小刚", 5000, 19),
new Employee("小凉", 7000, 40),
new Employee("小凉", 7000, 40),
new Employee("小凉", 7000, 40)
); @Test
public void test2() {
//filter是内部迭代,
//也就是StreamAPI内部实现的迭代不需要使用者再次手写迭代
employees.stream()
.filter((e) -> {
//System.out.println("进入过滤器");
return e.getSalary() > 7000.0;
})
.forEach((e) -> System.out.println(e.getSalary()));
System.out.println("-----------------------"); //测试limit(n)取前n个元素
employees.stream()
.limit(3)
.forEach((e) -> System.out.println(e)); System.out.println("-----------------------");
//skip(n)测试 舍掉前n个元素,去剩下后面的
employees.stream()
.skip(3)
.forEach((e) -> System.out.println(e)); System.out.println("=============================");
//distinct()去除重复,按照streamAPI中的hashCode和equals方法
employees.stream()
.distinct()
.forEach((e) -> System.out.println(e));
}
}

注意:distinct方法去除重复,需要实现pojo的hashCode()和equals().
控制台输出:

12000.0
8000.0
-----------------------
Employee{name='小明', salary=12000.0, age=32}
Employee{name='小红', salary=8000.0, age=23}
Employee{name='小刚', salary=5000.0, age=19}
-----------------------
Employee{name='小凉', salary=7000.0, age=40}
Employee{name='小凉', salary=7000.0, age=40}
Employee{name='小凉', salary=7000.0, age=40}
=============================
Employee{name='小明', salary=12000.0, age=32}
Employee{name='小红', salary=8000.0, age=23}
Employee{name='小刚', salary=5000.0, age=19}
Employee{name='小凉', salary=7000.0, age=40}

映射
map——接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
flatMap——接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流。

public static Stream<Character> getCharacter(String str) {
List<Character> list = new ArrayList<>(); for (Character character : str.toCharArray()) {
list.add(character);
}
return list.stream();
} @Test
public void test3() {
/**
* map,flapMap
*/ List<String> list = Arrays.asList("cvt", "aer", "ktv", "dbms"); //1.将list中的每个元素都转换成大写
list.stream()
.map((e) -> e.toUpperCase())
.forEach(System.out::println); System.out.println("------水平分割线---------");
//2.取出employees中的每个员工姓名输出
employees.stream()
.map((e) -> e.getName())
.forEach(System.out::println);
System.out.println("------水平分割线---------"); Stream<Character> sm = list.stream()
.flatMap(StreamAPITest::getCharacter); sm.forEach(System.out::println); }
排序

这个默认的是从小到大,可以自定义排序

//排序
List<Integer> list = Arrays.asList(12, 32, 2, 45, 38, 29); list.stream()
.sorted()
.forEach(System.out::println);//默认排序,从小到大 System.out.println("-------------------------"); //定制排序 employees 先按照月薪排序,如果月薪相等按照年龄排序 employees.stream()
.sorted((e1, e2) -> {
if (e1.getSalary() == e2.getSalary()) {
return e1.getAge().compareTo(e2.getAge()) ;
} else {
return e1.getSalary().compareTo( e2.getSalary());
}
})
.forEach(System.out::println);

运行结果:

12
29
32
38
45
-------------------------
Employee{name='小刚', salary=5000.0, age=19}
Employee{name='小凉', salary=7000.0, age=40}
Employee{name='小谷', salary=7000.0, age=20}
Employee{name='小红', salary=8000.0, age=23}
Employee{name='小明', salary=12000.0, age=32}
查找与匹配

allMatch ——检查是否匹配所有元素
anyMatch——检查是否至少匹配一个元素
noneMatch——检查是否没有匹配所有元素
findFirst——返回第一个元素
findAny——返回当前流中的任意元素
count——返回流中元素的总个数
max——返回流中最大值
min——返回流中最小值


private List<Employee> employees = Arrays.asList(
new Employee("小明", 12000.0, 32, Employee.Status.VOCATION),
new Employee("小红", 8000.0, 23, Employee.Status.FREE),
new Employee("小刚", 5000.0, 19, Employee.Status.BUSY),
new Employee("小凉", 7000.0, 40, Employee.Status.BUSY),
new Employee("小谷", 7000.0, 20, Employee.Status.FREE)
); //匹配、查找、最大值、最小值、
@Test
public void test5() {
//allMatch,如果所有的元素都匹配返回true,否则返回false
boolean b1 = employees.stream()
.allMatch((e) -> {
return e.getStatus() == Employee.Status.BUSY;
});
System.out.println("b1 = " + b1); //anyMatch 匹配中的任意元素满足条件返回true
boolean b2 = employees.stream()
.anyMatch((e) -> e.getStatus() == Employee.Status.VOCATION);
System.out.println("b2 = "+b2); //noneMatch 如果所有元素都满足条件返回true,否则返回false
boolean b3 = employees.stream()
.noneMatch((e) -> e.getStatus() == Employee.Status.FREE);
//并不是所有的员工状态都是free所以返回false
System.out.println("b3 = "+b3); //findFirst 查找第一个元素
Optional<Employee> employee1 = employees.stream()
.sorted((e1,e2)->-e1.getSalary().compareTo(e2.getSalary()))//salary 从高到低,返回最高工资的员工对象
.findFirst();
System.out.println("firstSalaryEmployee : "+employee1); //findAny 返回当前流中任意一个元素
Optional<Employee> any = employees.parallelStream()//parallelStream 并行流
.findAny();
System.out.println("any : "+any); //max
Optional<Employee> max = employees.stream()
.max((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
System.out.println("max age employee "+max); //min
Optional<Employee> min = employees.stream()
.min((e1, e2) -> e1.getAge().compareTo(e2.getAge()));
System.out.println("min age employee "+min); //count
long count = employees.stream()
.count();
System.out.println("count: "+count);
}


运行结果输出:

b1 = false
b2 = true
b3 = false
firstSalaryEmployee : Optional[Employee{name='小明', salary=12000.0, age=32}]
any : Optional[Employee{name='小刚', salary=5000.0, age=19}]
max age employee Optional[Employee{name='小凉', salary=7000.0, age=40}]
min age employee Optional[Employee{name='小刚', salary=5000.0, age=19}]
count: 5
归约

reduce(T identity,BinaryOperator)
reduce(BinaryOperator)
作用:可以将流中元素反复结合起来,得到一个值。

List<Integer> list = Arrays.asList(23,12,3,45,67,29,98);
Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println("sum = "+sum); //先从employees中取出salary,然后reduce做处理,将员工工资求和
Optional<Double> optionalDouble = employees.stream()
.map(Employee::getSalary)
.reduce(Double::sum); System.out.println(optionalDouble.get());

收集
collect——将流转成其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。

public void test7(){
//收集员工名字返回集合 //返回List
List<String> names = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
names.forEach(System.out::println);
//返回指定集合
HashSet<String> strings = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));
System.out.println(strings); }
结果:
小明
小红
小刚
小凉
小谷
[小刚, 小凉, 小谷, 小明, 小红]

使用collect从employees 中获取最大工资的人,最小工资,平均工资,员工工资总和,员工人数

@Test
public void test1() {
//count
Long count = employees.stream()
.collect(Collectors.counting());
System.out.println("count = " + count); //max employee
Optional<Employee> maxSalary = employees.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(maxSalary.get()); //min
Optional<Employee> minSal = employees.stream()
.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(minSal.get()); //avg salary
Double avgSal = employees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println("avg salary = "+avgSal); //sum salary
Double sumSal = employees.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println("sum salary = "+sumSal);
}
输出结果:

count = 5
Employee{name=‘小明’, salary=12000.0, age=32}
Employee{name=‘小刚’, salary=5000.0, age=19}
avg salary = 7800.0
sum salary = 39000.0

分组

@Test
public void test2(){ String collect = employees.stream()
.map(Employee::getName)
.collect(Collectors.joining(",","---","---"));//将取出的name连接在一起,中间用,隔开,前缀是‘---’,后缀也是'---'. System.out.println(collect); Map<Employee.Status, List<Employee>> collect1 = employees.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println("按状态分组:"+collect1);
}

输出结果:
—小明,小红,小刚,小凉,小谷—
按状态分组:{BUSY=[Employee{name=‘小刚’, salary=5000.0, age=19}, Employee{name=‘小凉’, salary=7000.0, age=40}], VOCATION=[Employee{name=‘小明’, salary=12000.0, age=32}], FREE=[Employee{name=‘小红’, salary=8000.0, age=23}, Employee{name=‘小谷’, salary=7000.0, age=20}]}

java8新特性之stream流的更多相关文章

  1. 乐字节-Java8新特性之Stream流(上)

    上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...

  2. 【Java8新特性】- Stream流

    Java8新特性 - Stream流的应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...

  3. Java8新特性之Stream流(含具体案例)

    一.概述   Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选.排序.聚合等.元素 ...

  4. JDK8新特性关于Stream流

    在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: 1 2 3 ...

  5. Java 8 新特性之 Stream 流基础体验

    Java 8 新特性之 Stream 流基础体验 package com.company; import java.util.ArrayList; import java.util.List; imp ...

  6. Java8 新特性之Stream API

    1. Stream 概述 Stream 是Java8中处理集合的关键抽象概念,可以对集合执行非常复杂的查找,过滤和映射数据等操作; 使用 Stream API 对集合数据进行操作,就类似于使用 SQL ...

  7. java1.8新特性之stream流式算法

    在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: List& ...

  8. 【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!

    写在前面 在上一篇<[Java8新特性]面试官问我:Java8中创建Stream流有哪几种方式?>中,一名读者去面试被面试官暴虐!归根结底,那哥儿们还是对Java8的新特性不是很了解呀!那 ...

  9. Java8新特性 1——利用流和Lambda表达式操作集合

    Java8中可以用简洁的代码来操作集合,比如List,Map,他们的实现ArrayList.以此来实现Java8的充分利用CPU的目标. 流和Lambda表达式都是Java8中的新特性.流可以实现对集 ...

随机推荐

  1. Codeforces Edu Round 56 A-D

    A. Dice Rolling 把\(x\)分解为\(a * 6 + b\),其中\(a\)是满6数,\(b\)满足\(1 <= b < 6\),即可... #include <io ...

  2. hash相关

    转译☞:https://www.cs.rice.edu/~as143/COMP441_Spring17/scribe/lect4.pdf 1 大规模图片检索问题 基于树模型的算法在分类跟聚类中很受欢迎 ...

  3. NetCDF格式.nc

    netcdf sfc_pres_temp { dimensions: latitude = 6 ; //纬度轴 longitude = 12 ; //经度轴 variables: float lati ...

  4. Linux 查看CPU型号,内存大小,硬盘空间的命令

    1 查看CPU 1.1 查看CPU个数 # cat /proc/cpuinfo | grep "physical id" | uniq | wc -l 1.2 查看CPU核数 # ...

  5. Asp.net core验证类ModelStateDictionary的bug

    在使用.net core 3.1 时发现明明没有验证请求类属性,甚至已经加了默认值 但是验证类时依然会报错 经过网上百度等搜索,尝试使用可空类型赋值默认值 果然验证类没有报错 不清楚是微软的bug还是 ...

  6. 庐山真面目之八微服务架构 NetCore 基于 Dockerfile 文件部署

    庐山真面目之八微服务架构 NetCore 基于 Dockerfile 文件部署 一.简介      从今天开始,不出意外的话,以后所写的文章中所介绍项目的部署环境都应该会迁移到Linux环境上,而且是 ...

  7. 详解Java中的IO输入输出流!

    目录 本片要点 基本分类 发展史 文件字符流 输出的基本结构 流中的异常处理 异常处理新方式 读取的基本结构 运用输入与输出完成复制效果 文件字节流 缓冲流 字符缓冲流 装饰设计模式 转换流(适配器) ...

  8. python 安装相关

    一.安装python 1.官网下载python 1.1 可下载绿色版 2.2 也可下载安装版,安装时可自动安装pip 和 自动配置环境变量 2.手动配置环境变量,我的电脑>属性>高级> ...

  9. 关于 Softmax 回归的反向传播求导数过程

    对于 \(Softmax\) 回归的正向传播非常简单,就是对于一个输入 \(X\) 对每一个输入标量 \(x_i\) 进行加权求和得到 \(Z\) 然后对其做概率归一化. Softmax 示意图 下面 ...

  10. Spring-IOC注解编程

    这里的注解是最初级的一些注解,掌握了之后再学习其它的注解 注解扫描 <?xml version="1.0" encoding="UTF-8"?> & ...