java8新特性stream笔记
1.0概述
java8是一个非常成功的版本,这个版本新增的Stream,配合同版本出现过lamda,给们操作集合(Collection)提供了极大的便利。Stream流是JDK8新增的成员,允许以声明式的方式操作数据集合,可以将流作为遍历数据集合的高级迭代器。他可以指定你希望的集合进行操作,可以执行非常复杂的查找/筛选/过滤、排序、聚合和映射数据等操作,stream主要是迭代器的增强(大批量数据操作)
1.1.1使用流的好处
代码可以声明性方式书写,可以把其他几个基础操作连接起来,来表达复杂数据的处理流水线操作
1.1.2流是什么
从支持数据处理操作的源生成元素序列,数据源可以是结合,数组,IO
从操作看,流与集合是不同的,流不存储数据值;流的目的是处理数据,处理算法和计算
如果把集合作为流的数据源,创建流是不会导致数据流动,如果流的终止操作需要时,流会从集合中获取值
流的中心思想是延迟计算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Am9v4OJ5-1655544903419)(C:\Users\李嘉欣.LAPTOP-8M7U76TN\AppData\Roaming\Typora\typora-user-images\image-20220618163924990.png)]
流不会存储数据只是传输数据,不会改变,都是一次性的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9oc4VnUJ-1655544903420)(C:\Users\李嘉欣.LAPTOP-8M7U76TN\AppData\Roaming\Typora\typora-user-images\image-20220617111504201.png)]
Stream可以由数组和集合创建,对流的操作分为两种
中间操作,每次返回一个新的流,可以由多个
终止操作:每个流只能进行一次终端操作,终端操作结束后流无法再使用,终端操作会产生一个新的集合或值
特性:
不是数据结构,不会保存数据
不会修改原来的数据源他会将操作或的数据保存到另一个对象中
惰性计算,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0eNq6htS-1655544903421)(C:\Users\李嘉欣.LAPTOP-8M7U76TN\AppData\Roaming\Typora\typora-user-images\image-20220618164647880.png)]
2.0分类
过滤,排序-》》懒节点,采集-》》终值节点
stream流的操作 | 状态描述 | ||
---|---|---|---|
中间操作 | 无状态 | unordered() map() filter() mapToLong() mapToDouble() flatMap() flatMapToInt() flagMapToLong(0)flagMapToDouble() | 指元素的处理不受之前的元素影响 |
有状态 | distinct(),sorted(),limit() skip() | 指该操作只有拿到所有元素之后才能继续下去 | |
结束操作 | 非短路操作 | forEach() froEachOrdered() toArray() reduce() collect() max() min() count() | 指必须处理所有元素才能得到最终结果 |
短路操作 | anyMatch() allMatch() noneMAtch() fiandeFirst() findArray() | 指遇到某些符合的元素就可以得到最终的结果 |
3.0 Stream创建使用
List<String> list = Arrays.asList("a","b","c");
//创建一个顺序流(单线程处理)
Stream<String> stream = list.stream();
System.out.println(stream.count());
//创建一个并行流(多核处理)
Stream<String> syncstream = list.parallelStream();
System.out.println(syncstream);
3.1.1
数组创建
int array [] = {1,3,5,7,9};
IntStream stream1 = Arrays.stream(array);
使用Strea静态方法
Stream<Integer> stream2 = Stream.of(1,2,3,4,6);
stream2.forEach(System.out::print);
Stream<Integer> stream3 = Stream.iterate(0,(x)->x+3).limit(4);
stream3.forEach(System.out::println);
Stream<Double> stream4 = Stream.generate(Math::random).limit(4);
stream4.forEach(System.out::print);
4.0StreamAPI介绍
根据对象进行条件筛选
/**
* 筛选员工中已满18周岁的人,并形成新的集合
* @思路
* List<Person> list = new ArrayList<Person>();
* for(Person person : personList) {
* if(person.getAge() >= 18) {
* list.add(person);
* }
* }
*/
private static void filter01() {
initPerson();
List<Person> collect = personList.stream().filter(x -> x.getAge()>=18).collect(Collectors.toList());
System.out.println(collect);
}
获取String最长元素
/**
* 获取String集合中最长的元素
* @思路
* List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "sunliu");
* String max = "";
* int length = 0;
* int tempLength = 0;
* for(String str : list) {
* tempLength = str.length();
* if(tempLength > length) {
* length = str.length();
* max = str;
* }
* }
* @return zhangsan
*/
private static void test02() {
List<String> list = Arrays.asList("zhangsan", "lisi", "wangwu", "sunliu");
Comparator<? super String> comparator = Comparator.comparing(String::length);
Optional<String> max = list.stream().max(comparator);
System.out.println(max);
}
获取集合中的最大的元素
//获取Integer集合中的最大值
private static void test05() {
List<Integer> list = Arrays.asList(1, 17, 27, 7);
Optional<Integer> max = list.stream().max(Integer::compareTo);
// 自定义排序
Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
System.out.println(max2);
}
获取员工中年龄最大的人
private static void test06() {
initPerson();
Comparator<? super Person> comparator = Comparator.comparingInt(Person::getAge);
Optional<Person> max = personList.stream().max(comparator);
System.out.println(max);
}
map的使用
map和flatMap
map:接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素
flatMap:接受一个函数作为参数,将流中的每个值都换成流,然后把所有的流连接成一个流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4uWaEJuI-1655544903421)(C:\Users\李嘉欣.LAPTOP-8M7U76TN\AppData\Roaming\Typora\typora-user-images\image-20220617174112182.png)]
筛选条件相加
/**
* 整数数组每个元素+3
* @思路
* List<Integer> list = Arrays.asList(1, 17, 27, 7);
List<Integer> list2 = new ArrayList<Integer>();
for(Integer num : list) {
list2.add(num + 3);
}
@return [4, 20, 30, 10]
*/
private static void test09() {
List<Integer> list = Arrays.asList(1, 17, 27, 7);
List<Integer> collect = list.stream().map(x -> x + 3).collect(Collectors.toList());
System.out.println(collect);
}
对象数值相加
/**
* 公司效益好,每人涨2000
*
*/
private static void test10() {
initPerson();
List<Person> collect = personList.stream().map(x -> {
x.setAge(x.getSalary()+2000);
return x;
}).collect(Collectors.toList());
System.out.println(collect);
}
将两个字符串放入一个集合
/**
* 将两个字符数组合并成一个新的字符数组
* @return [z, h, a, n, g, s, a, n]
*/
private static void test11() {
String[] arr = {"z, h, a, n, g", "s, a, n"};
List<String> list = Arrays.asList(arr);
List<String> collect = list.stream().flatMap(x -> {
String[] array = x.split(",");
Stream<String> stream = Arrays.stream(array);
return stream;
}).collect(Collectors.toList());
System.out.println(collect);
}
规约reduce
缩减,将一个流缩减成一个数值(加和,乘除,求解最大最小值)
/**
* 求Integer集合的元素之和、乘积和最大值
*
*/
private static void test13() {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
//求和
Optional<Integer> reduce = list.stream().reduce((x,y) -> x+ y);
System.out.println("求和:"+reduce);
//求积
Optional<Integer> reduce2 = list.stream().reduce((x,y) -> x * y);
System.out.println("求积:"+reduce2);
//求最大值
Optional<Integer> reduce3 = list.stream().reduce((x,y) -> x>y?x:y);
System.out.println("求最大值:"+reduce3);
}
collect
Collectors提供了一系列用于数据统计的静态方法
计数:count
平均值:averagIngInt,averagingLong,averagingDouble
最大值:maxBy,minBy
求和:summingInt,summingLong,summingDouble
统计以上所有:summarizingInt,summarizingLong,summarizingDouble
public void personinf(){
initPerson();
Long count = personList.stream().collect(Collectors.counting());
System.out.println(count);
Double average = personList.stream().collect(Collectors.averagingDouble(Persion::getNum));
System.out.println(average);
Optional<Integer> optional = personList.stream().map(Persion::getNum).collect(Collectors.maxBy(Integer::compareTo));
System.out.println(optional);
Integer sum = personList.stream().collect(Collectors.summingInt(Persion::getNum));
System.out.println(sum);
DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Persion::getNum));
System.out.println(collect);
}
分组
分区:将stream按条件分为两个Map,比如员工按薪资分为高于某个范围值的两部分
分组:将集合分为多个Map,比如按性别筛选,可单级分组和多级分组
public class StreamTest {
public static void main(String[] args) {
personList.add(new Person("zhangsan",25, 3000, "male", "tieling"));
personList.add(new Person("lisi",27, 5000, "male", "tieling"));
personList.add(new Person("wangwu",29, 7000, "female", "tieling"));
personList.add(new Person("sunliu",26, 3000, "female", "dalian"));
personList.add(new Person("yinqi",27, 5000, "male", "dalian"));
personList.add(new Person("guba",21, 7000, "female", "dalian"));
// 将员工按薪资是否高于8000分组
Map<Boolean, List<Person>> part = personList.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 8000));
// 将员工按性别分组
Map<String, List<Person>> group = personList.stream().collect(Collectors.groupingBy(Person::getSex));
// 将员工先按性别分组,再按地区分组
Map<String, Map<String, List<Person>>> group2 = personList.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
System.out.println("员工按薪资是否大于8000分组情况:" + part);
System.out.println("员工按性别分组情况:" + group);
System.out.println("员工按性别、地区:" + group2);
}
}
public void CollectTest(){
initPerson();
Map<Boolean,List<Persion>> map = personList.stream().collect(Collectors.partitioningBy(x -> x.getNum() > 8000));
Map<String,List<Persion>> group = personList.stream().collect(Collectors.groupingBy(Persion::getSex));
System.out.println(group);
System.out.println(map);
Map<String,Map<String,List<Persion>>> doublegroup = personList.stream().collect(Collectors.groupingBy(Persion::getSex,Collectors.groupingBy(Persion::getLocal)));
System.out.println(doublegroup);
List<String>list = personList.stream().map(x_-> x_.getName()).collect(Collectors.toList());
System.out.println(list);
}
排序
private static void test04(){
// 按工资升序排序(自然排序)
List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
.collect(Collectors.toList());
// 按工资倒序排序
List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
.map(Person::getName).collect(Collectors.toList());
// 先按工资再按年龄升序排序
List<String> newList3 = personList.stream()
.sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
.collect(Collectors.toList());
// 先按工资再按年龄自定义排序(降序)
List<String> newList4 = personList.stream().sorted((p1, p2) -> {
if (p1.getSalary() == p2.getSalary()) {
return p2.getAge() - p1.getAge();
} else {
return p2.getSalary() - p1.getSalary();
}
}).map(Person::getName).collect(Collectors.toList());
System.out.println("按工资升序排序:" + newList);
System.out.println("按工资降序排序:" + newList2);
System.out.println("先按工资再按年龄升序排序:" + newList3);
System.out.println("先按工资再按年龄自定义降序排序:" + newList4);
}
提取合并
private static void test05(){
String[] arr1 = { "a", "b", "c", "d" };
String[] arr2 = { "d", "e", "f", "g" };
Stream<String> stream1 = Stream.of(arr1);
Stream<String> stream2 = Stream.of(arr2);
// concat:合并两个流 distinct:去重
List<String> newList = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
// limit:限制从流中获得前n个数据
List<Integer> collect = Stream.iterate(1, x -> x + 2).limit(10).collect(Collectors.toList());
// skip:跳过前n个数据
List<Integer> collect2 = Stream.iterate(1, x -> x + 2).skip(1).limit(5).collect(Collectors.toList());
System.out.println("流合并:" + newList);
System.out.println("limit:" + collect);
System.out.println("skip:" + collect2);
}
map的使用字符串转换
public void sexgroup(){
initPerson();
personList.stream().filter(a->a.getLocal().equals("tieling")).map(a->a.getLocal())
.distinct()
.peek(c-> System.out.println(c)).toArray();
}