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. 题解-洛谷P7114 字符串匹配

    题面 洛谷P7114 字符串匹配 \(T\) 组测试数据.给定字符串 \(S\),问有多少不同的非空字符串 \(A\),\(B\),\(C\) 满足 \(S=ABABAB...ABC\) 且 \(A\ ...

  2. CF1457D XOR-gun

    这道题真的把我秀到了,我首先猜了一波结论,打了一个可持久化 \(\text{Trie}\) 加二分的两只 \(\log_2\) 的做法,发现不能 \(PP\) ,然后就一直改到比赛结束还没改过. 然后 ...

  3. Mycat配置分库分表(垂直分库、水平分表)、全局序列

    1. Mycat相关文章   Linux安装Mycat1.6.7.4并实现Mysql数据库读写分离简单配置   Linux安装Mysql8.0.20并配置主从复制(一主一从,双主双从)   Docke ...

  4. python 爬虫库安装

    一键安装python爬虫库 pip3 install requests selenium beautifulsoup4 pyquery pymysql pymongo redis flask djan ...

  5. Flink读写Redis(一)-写入Redis

    项目pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...

  6. oracle 常用语句2

    -- number(38) -- char(2000) -- varchar(4000) create table student( sno number(3) primary key, sname ...

  7. [日常摸鱼][poj2777]Count Color-线段树

    辣鸡会考考完啦哈哈哈哈 题意:一块板分成$L$块,每次给一段连续的块染色或者询问一段有几种颜色,颜色的范围$\leq 30$ 我记得我好像做过一个类似的二维染色的问题-不过那个用树状数组直接过掉了- ...

  8. 仵航说 SpringBoot项目配置Log日志服务-仵老大

    今天领导让我配置一个log日志服务,我哪里见过哟,然后就去百度了,结果挨个试下去,找到了一个能用的,分享给大家 大致四个地方 分别是 1.pom文件需要引入依赖 2.创建一个TestLog类 3.在y ...

  9. 逆袭故事|从“点点点”到月薪17K,这个女孩子做到啦

    姓:XXX,XX VIP 学员,一名自动化测试工程师!之前在某大型培训机构转行学习软件测试时就是木子老师的学生,她也一直关注木子老师的动态,后来知道木子老师打算开设测试开发高级提升班,等开了班就报名了 ...

  10. PHPSHE 1.7前台SQL注入漏洞分析

    此CMS  SQL注入漏洞产生原因为未将经过 addslashes() 函数过滤的数据使用单引号包裹,从而导致的SQL注入漏洞.接下来看漏洞详情: 首先查看phpshe下的common.php文件37 ...