java8新特性之stream流
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流的更多相关文章
- 乐字节-Java8新特性之Stream流(上)
上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...
- 【Java8新特性】- Stream流
Java8新特性 - Stream流的应用 生命不息,写作不止 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 分享学习心得,欢迎指正,大家一起学习成长! ...
- Java8新特性之Stream流(含具体案例)
一.概述 Stream 流是 Java 8 新提供给开发者的一组操作集合的 API,将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选.排序.聚合等.元素 ...
- JDK8新特性关于Stream流
在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: 1 2 3 ...
- Java 8 新特性之 Stream 流基础体验
Java 8 新特性之 Stream 流基础体验 package com.company; import java.util.ArrayList; import java.util.List; imp ...
- Java8 新特性之Stream API
1. Stream 概述 Stream 是Java8中处理集合的关键抽象概念,可以对集合执行非常复杂的查找,过滤和映射数据等操作; 使用 Stream API 对集合数据进行操作,就类似于使用 SQL ...
- java1.8新特性之stream流式算法
在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: List& ...
- 【Java8新特性】Stream API有哪些中间操作?看完你也可以吊打面试官!!
写在前面 在上一篇<[Java8新特性]面试官问我:Java8中创建Stream流有哪几种方式?>中,一名读者去面试被面试官暴虐!归根结底,那哥儿们还是对Java8的新特性不是很了解呀!那 ...
- Java8新特性 1——利用流和Lambda表达式操作集合
Java8中可以用简洁的代码来操作集合,比如List,Map,他们的实现ArrayList.以此来实现Java8的充分利用CPU的目标. 流和Lambda表达式都是Java8中的新特性.流可以实现对集 ...
随机推荐
- 题解-洛谷P7114 字符串匹配
题面 洛谷P7114 字符串匹配 \(T\) 组测试数据.给定字符串 \(S\),问有多少不同的非空字符串 \(A\),\(B\),\(C\) 满足 \(S=ABABAB...ABC\) 且 \(A\ ...
- CF1457D XOR-gun
这道题真的把我秀到了,我首先猜了一波结论,打了一个可持久化 \(\text{Trie}\) 加二分的两只 \(\log_2\) 的做法,发现不能 \(PP\) ,然后就一直改到比赛结束还没改过. 然后 ...
- Mycat配置分库分表(垂直分库、水平分表)、全局序列
1. Mycat相关文章 Linux安装Mycat1.6.7.4并实现Mysql数据库读写分离简单配置 Linux安装Mysql8.0.20并配置主从复制(一主一从,双主双从) Docke ...
- python 爬虫库安装
一键安装python爬虫库 pip3 install requests selenium beautifulsoup4 pyquery pymysql pymongo redis flask djan ...
- Flink读写Redis(一)-写入Redis
项目pom文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...
- oracle 常用语句2
-- number(38) -- char(2000) -- varchar(4000) create table student( sno number(3) primary key, sname ...
- [日常摸鱼][poj2777]Count Color-线段树
辣鸡会考考完啦哈哈哈哈 题意:一块板分成$L$块,每次给一段连续的块染色或者询问一段有几种颜色,颜色的范围$\leq 30$ 我记得我好像做过一个类似的二维染色的问题-不过那个用树状数组直接过掉了- ...
- 仵航说 SpringBoot项目配置Log日志服务-仵老大
今天领导让我配置一个log日志服务,我哪里见过哟,然后就去百度了,结果挨个试下去,找到了一个能用的,分享给大家 大致四个地方 分别是 1.pom文件需要引入依赖 2.创建一个TestLog类 3.在y ...
- 逆袭故事|从“点点点”到月薪17K,这个女孩子做到啦
姓:XXX,XX VIP 学员,一名自动化测试工程师!之前在某大型培训机构转行学习软件测试时就是木子老师的学生,她也一直关注木子老师的动态,后来知道木子老师打算开设测试开发高级提升班,等开了班就报名了 ...
- PHPSHE 1.7前台SQL注入漏洞分析
此CMS SQL注入漏洞产生原因为未将经过 addslashes() 函数过滤的数据使用单引号包裹,从而导致的SQL注入漏洞.接下来看漏洞详情: 首先查看phpshe下的common.php文件37 ...