0
点赞
收藏
分享

微信扫一扫

java 1.8 stream使用总结(个人总结有一些经典文章的集合)

A邱凌 2022-04-13 阅读 16
java

stream是jdk1.8引入的一个新概念,把列表流stream化,然后再加工成我们想要的列表或者别的数据
我们经常会对列表list数据用for循环,用stream来替换for循环会更简洁。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

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

为什么要有stream?实际开发中,项目中多数数据来源都来自Mysql,Oracle等。打死你hi现在数据源更多了,比如MongDb,Redis等,而这些Nosql的数据就需要Java层面去处理了。
在这里插入图片描述
Stream的api大体上分为两种:中间操作符和终止操作符

补充1:Stream与Collection集合的区别:

补充2:

stream的操作有三个步骤:

1.创建Stream:一个数据源(如 集合,数组)从而获取一个Stream,泛型最好带着,因为有时候不带使用lambda的时候会有类型错误,默认其泛型为obeject的流。
2.中间操作 : 一个中间操作链,对数据源的数据进行处理。(代码中演示)
3.终止操作:一旦执行终止操作 ,就执行了中间操作链,并产生结果,之后就不会再被使用。这也是为什么说Stream是延迟执行的原因。

步骤1 生成stream的四种方式

方式1–通过集合
这种方式是最简单的一种创建stream的方式,直接通过集合调用方法即可得到;

package com.example.demoTest;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class test1 {

    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
//  创建一个Stream

        //  返回一个顺序操作的stream   从上倒下的操作
        Stream stream1 = list.stream();
        //  返回一个并行操作的stream    有几个线程会同时运行,所以数据有可能乱
        Stream stream2 = list.parallelStream();

         stream1.forEach(stream3 -> System.out.println("stream1==>"+stream3));

        stream2.forEach(System.out::println);
    }
}

运行结果

stream1==>a
stream1==>b
stream1==>c
stream1==>d
c
d
a
b

创建方式2–通过数组
这一种是调用Arrays类的中的方法,进行创建的。

package com.example.demoTest;

import java.util.Arrays;
import java.util.stream.Stream;

public class test2 {

    public static void main(String[] args) {
        String[] arr= {"a","b"};
        Stream<String> stream= Arrays.stream(arr); // 这种也可以创建自定义的类类型 是顺序
        stream.forEach(System.out::println);

    }

}

运行结果为

a
b

创建方式3–of方法

Stream本身就有一个方法of()

package com.example.demoTest;

import java.util.stream.Stream;

public class test3 {

    public static void main(String[] args) {
        Stream<String> steam=Stream.of("a","b"); // 这种也可以创建自定义的类类型  是顺序

        steam.forEach(System.out::println);
    }


}

运行结果为

a
b

创建方式4-无限流

package com.example.demoTest;

import java.util.stream.Stream;

public class test4 {
    public static void main(String[] args) {
        // 无限流第一种  迭代
        // 其中这个方法用到了Function<T, T> 接口的子接口   public interface UnaryOperator<T> extends Function<T, T>
        // 这个地方其实也用了中间操作 limit  以及终止操作  forEach 不然无法体现出效果
        Stream.iterate(0, t-> t=t+1).limit(5).forEach(System.out::println);
    }
}

运行结果是

0
1
2
3
4
package com.example.demoTest;

import java.util.function.Supplier;
import java.util.stream.Stream;

public class test4 {
//    public static void main(String[] args) {
//        // 无限流第一种  迭代
//        // 其中这个方法用到了Function<T, T> 接口的子接口   public interface UnaryOperator<T> extends Function<T, T>
//        // 这个地方其实也用了中间操作 limit  以及终止操作  forEach 不然无法体现出效果
//        Stream.iterate(0, t-> t=t+1).limit(5).forEach(System.out::println);
//
//    }



        public static void main(String[] args) {
            // 无限流第二种  生成
            // 其中这个方法用到了Supplier<T>      public static<T> Stream<T> generate(Supplier<T> s) {
            // 这个地方其实也用了中间操作 limit  以及终止操作  forEach 不然无法体现出效果
            // 普通写法
            Stream.generate(new Supplier<Double>() {
                @Override
                public Double get() {
                    // TODO Auto-generated method stub
                    return Math.random();
                }
            }).limit(10).forEach(System.out::println);

            // 方法引用
            // Supplier<T>  实现的方法中一行代码 通过 Math用random方法,所以可以用方法引用

            Stream.generate(Math::random).limit(10).forEach(System.out::println);

        }
}

运行结果是

0.1152754126322737
0.4055938751525989
0.22566579693444688
0.30862268419462036
0.5122102416859415
0.9228326075570314
0.7545369056864921
0.49667141028003825
0.37913763643364573
0.29365610054552227
0.86781437089616
0.4828942924408204
0.9876446244541521
0.9718941206628138
0.563001739077662
0.9088142972006622
0.15000071455924757
0.7425350588111158
0.6468398223925326
0.5391449572854645

中间操作符:

filter
可以通过 filter 方法将一个流转换成另一个子集流

map
可以通过map 方法将一个流映射成另一个流

sort
在流里面进行排序

limit
限制流,例如只取前流的前几个元素

skip
跳过操作,例如跳过流的前几个元素

count
统计个数,正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数

终止操作符:

collect
收集操作,将所有数据收集起来,Stream 的核心在于Collectors,常用的Collectors.toSet()、Collectors.toList()、Collectors.groupingBy()。
count
统计操作,统计最终的数据个数。
findFirst、findAny
查找操作,查找第一个、查找任何一个 返回的类型为Optional。
noneMatch、allMatch、anyMatch
匹配操作,数据流中是否存在符合条件的元素 返回值为bool 值。
min、max
最值操作,需要自定义比较器,返回数据流中最大最小的值。
reduce
规约操作,将整个数据流的值规约为一个值,count、min、max底层就是使用reduce。
forEach、forEachOrdered
遍历操作,这里就是对最终的数据进行消费了。
toArray
数组操作,将数据流的元素转换成数组。

可以通过Collection系列集合提供的stream() 串行 或 parallelStream() 并行

    public static void main(String[] args) {
        //可以通过Collection系列集合提供的stream() 串行 或 parallelStream() 并行
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();
 
        //通过Arrays中的静态方法stream()获取 数组流
        LoginRequest[] loginRequests = new LoginRequest[10];
        Stream<LoginRequest> stream1 = Arrays.stream(loginRequests);
 
        //通过stream类中的静态方法of()
        Stream<String> aa = Stream.of("aa");
 
        //创建 无限流
            //迭代
        Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
        //iterate.limit(10) 就是中间操作
        //forEach(System.out::println) 就是终止操作
        iterate.limit(10).forEach(System.out::println);
    }
 
//并行流 parallelStream
    public static void main(String[] args) {
        List<Integer>  list  =  new ArrayList<>();
        for (int j = 0; j < 1000; j++) {
            list.add(j);
        }
        System.out.println("最开始生成的集合长度:"+list.size());
        //parallelStream遍历数据的时候会产生丢失的问题
        for (int i = 0; i < 10 ; i++) {
 
            List<Integer> parseList = new ArrayList<>();
            List<Integer> synchronizedList = Collections.synchronizedList(parseList);
            list.parallelStream().forEach(integer -> {
                synchronizedList.add(integer);
            });
            System.out.println("每次遍历的集合长度:"+ synchronizedList.size());
        }
    }

实体类通用:

package com.example.demoTset2;

import lombok.Data;

@Data
public class login {

    public String name;
    public String passWord;
    public String age;

}

串行

public static void main(String[] args) {
        //可以通过Collection系列集合提供的stream() 串行 或 parallelStream() 并行
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

        //通过Arrays中的静态方法stream()获取 数组流
        login[] loginRequests = new login[10];
        Stream<login> stream1 = Arrays.stream(loginRequests);

        //通过stream类中的静态方法of()
        Stream<String> aa = Stream.of("aa");

        //创建 无限流
        //迭代
        Stream<Integer> iterate = Stream.iterate(0, (x) -> x + 2);
        //iterate.limit(10) 就是中间操作
        //forEach(System.out::println) 就是终止操作
        iterate.limit(10).forEach(System.out::println);
    }

运行结果

0
2
4
6
8
10
12
14
16
18

并行流

  //并行流 parallelStream
    public static void main(String[] args) {
        List<Integer>  list  =  new ArrayList<>();
        for (int j = 0; j < 1000; j++) {
            list.add(j);
        }
        System.out.println("最开始生成的集合长度:"+list.size());
        //parallelStream遍历数据的时候会产生丢失的问题
        for (int i = 0; i < 10 ; i++) {

            List<Integer> parseList = new ArrayList<>();
            List<Integer> synchronizedList = Collections.synchronizedList(parseList);
            list.parallelStream().forEach(integer -> {
                synchronizedList.add(integer);
            });
            System.out.println("每次遍历的集合长度:"+ synchronizedList.size());
        }
    }

结果

最开始生成的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000
每次遍历的集合长度:1000

常用方法 筛选与切片:

方法作用
filter(Predicate p)接受一个lambda,从stream中按照要求得得到数据
limit(n)截断数据,是数据不要超过n个
skip(n)跳过元素,返回一个跳过的n个元素的stream,若不足n个返回一个空流。
distinct()通过元素的hashcode和equals去除重复元素

实体类

package com.example.demoTset2;

import lombok.Data;

@Data
public class login {

    public String name;
    public String passWord;
    public String age;


    public  login(String name, String passWord, String age) {
        super();
        this.name = name;
        this.passWord = passWord;
        this.age = age;
    }
}

filter 筛选

选出age为22的数组

package com.example.demoTset2;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Filter {


    static List<login> login = Arrays.asList(
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("王五", "3333", "33"),
            new login("赵六", "6666", "66")
    );


    public static void main(String[] args) {
        Stream<login> loginRequestStream = login.stream().filter((e) -> "22".equals(e.getAge()));
        loginRequestStream.forEach(System.out::println);
    }

}

运行结果为

login(name=李四, passWord=2222, age=22)

limit截断

 static List<login> login = Arrays.asList(
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("王五", "3333", "33"),
            new login("赵六", "6666", "66")
    );

  //limit截断:
    public static void main(String[] args) {
        login.stream()
                .filter((e) -> Integer.valueOf(e.getAge()) > 11)
                .limit(1)//需要几条数据 截几条 例如:1条就是1
                .forEach(System.out::println);
    }

运行结果是

login(name=李四, passWord=2222, age=22)

skip 跳过:

 static List<login> login = Arrays.asList(
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("王五", "3333", "33"),
            new login("赵六", "6666", "66")
    );
    
//skip 跳过
    public static void main(String[] args) {
        login.stream()
                .filter((e) -> Integer.valueOf(e.getAge()) > 11)
                .skip(1)//跳过2条数据 下标0,1
                .forEach(System.out::println);
    }

login(name=王五, passWord=3333, age=33)
login(name=赵六, passWord=6666, age=66)

distinct 去重


    static List<login> login = Arrays.asList(
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),

            new login("王五", "3333", "33"),
            new login("赵六", "6666", "66")
    );
//distinct 去重
    public static void main(String[] args) {
        login.stream()
                .filter((e) -> Integer.valueOf(e.getAge()) > 1)
                .distinct()
                .forEach(System.out::println);
    }

运行结果:

login(name=张三, passWord=1111, age=11)
login(name=李四, passWord=2222, age=22)
login(name=王五, passWord=3333, age=33)
login(name=赵六, passWord=6666, age=66)

包含contains 两种实现方式:

 static List<login> login = Arrays.asList(
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),

            new login("王五", "3333", "33"),
            new login("赵六", "6666", "66")
    );

 static List<login> login = Arrays.asList(
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),
            new login("张三", "1111", "11"),
            new login("李四", "2222", "22"),

            new login("王五", "3333", "33"),
            new login("赵六", "6666", "66")
    );

 public static void main(String[] args) {

        Stream<login> stream = login.stream();
        stream.filter(t-> t.getName().contains("张三")).limit(3).forEach(System.out::println);

        System.out.println("-----------分割线-------");

        stream = login.stream();
        Stream<String> stream1= stream.map(t ->  t.getName());

        stream1.filter(t -> t.contains("张三")).forEach(System.out::println);
        
    }

运行结果为

login(name=张三, passWord=1111, age=11)
login(name=张三, passWord=1111, age=11)
login(name=张三, passWord=1111, age=11)
-----------分割线-------
张三
张三
张三

映射

方法映射
map(Function f)将函数作为要给参数,该函数会被应用到每一个元素上,产生一个新的DoubleStream。当然类似的还有:map ToLong(ToLongFunction f) ,mapToInt(ToIntFunction f) 等
flatMap(Function f)将一个函数作为参数,将流(stream)中的每个值都换成另一个流,然后把所有的流连接成

map 接受lambda,讲元素转成其他形式或提取信息,接受一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素.

flagMap 接收一个函数作为参数,将流中的每一个值都转换成另一个流,然后把所有的流了解成一个流.

toUpperCase 转成大写

public static void main(String[] args) {
        List<String> list = Arrays.asList("aaa", "bbb","www","ccc", "ddd");
        list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);
    }

输出结果

AAA
BBB
WWW
CCC
DDD
package com.example.demoTset2;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Test1 {


//    public static void main(String[] args) {
//        List<String> list = Arrays.asList("aaa", "bbb","www","ccc", "ddd");
//        list.stream().map((str) -> str.toUpperCase()).forEach(System.out::println);
//    }


    public static void main(String[] args) {
        List<String> list=Arrays.asList("ab","cd","ef");
//		想要打印出 a b  c d  e f
//		 如果使用map
        Stream<String> stream=list.stream();
        Stream<Stream<Character>> streamCs= stream.map(Test1::abc);
        streamCs.forEach(streamC->
                streamC.forEach(System.out::println)
        );


        System.out.println("-----------分割线-------");

        //		 flatMap

        stream=list.stream();
        //Stream<Character> 这个直接将里面的集合进行展开

        Stream<Character> streamC=stream.flatMap(Test1::abc);
        streamC.forEach(System.out::println);


    }


//	将字符串拆成一个字符
    public static Stream<Character> abc(String str){
        List list=new ArrayList<>();
        for(Character c:str.toCharArray()) {
            list.add(c);
        }
        // 直接返回一stream 为了好操作
        return list.stream();
    }

}

运行结果是

a
b
c
d
e
f
-----------分割线-------
a
b
c
d
e
f

排序

方法作用
sorted()会生成一个新的流,将其按自然顺序排序
sorted(Comparator com )会生成一个新的流,将其按比较其顺序排序
package com.example.demoTset2;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Test2 {


    public static void main(String[] args) {
        List<Integer> list= Arrays.asList(1,3,2,6,5,8);
        Stream<Integer> stream=list.stream();
        Stream<Integer> stream1=stream.sorted();
        stream1.forEach(System.out::println);

        System.out.println("-----------分割线-------");
        stream=list.stream();
        stream1=stream.sorted((o1,o2) -> Integer.compare(o2, o1) );
        stream1.forEach(System.out::println);
    }

}

运作结果是

1
2
3
5
6
8
-----------分割线-------
8
6
5
3
2
1

终止操作

匹配与查找

方法作用
allMatch(Predicate p)检查是否匹配所有的元素,如果都满足返回true,哪怕一个不满足返回false
anyMatch(Predicate p)检查是否至少匹配一个元素,如果有一个以及一个以上返回true,否则返回false
noneMatch(Predicate p)检查是否没有匹配一个元素,哪怕一个满足返回false,否则返回true
findFirst()返回最后一个元素,不过其返回的是一个Optional类 (这个后面补充)
findAny()返回当前流中的任意元素,不过其返回的是一个Optional类

allMatch:检查是否匹配所有的元素,如果都满足返回true,哪怕一个不满足返回false

//检查是否匹配所有的元素,如果都满足返回true,哪怕一个不满足返回false
    public static void main(String[] args) {
        //值全部大于0
        List<Integer> list=Arrays.asList(1,3,2);
        Stream<Integer> stream=list.stream();
        boolean b=stream.allMatch(t -> t>0);
        System.out.println(b);
        System.out.println("-----------分割线-------");
        //值全部大于2
        stream=list.stream();
        b=stream.allMatch(t -> t>2);
        System.out.println(b);

    }
			

运行结果是

true
-----------分割线-------
false

anyMatch:检查是否至少匹配一个元素,如果有一个以及一个以上返回true,否则返回false

//检查是否至少匹配一个元素,如果有一个以及一个以上返回true,否则返回false
    public static void main(String[] args) {
        List<Integer> list=Arrays.asList(1,3,2);
        Stream<Integer> stream=list.stream();
        boolean b=stream.anyMatch(t -> t>0);
        System.out.println(b);
        System.out.println("-----------分割线-------");

        stream=list.stream();
        b=stream.anyMatch(t -> t>2);
        System.out.println(b);
    }

运行结果为

true
-----------分割线-------
true

noneMatch:检查是否没有匹配一个元素,哪怕一个满足返回false,否则返回true

//检查是否没有匹配一个元素,哪怕一个满足返回false,否则返回true
    public static void main(String[] args) {
        List<Integer> list=Arrays.asList(1,3,2);
        Stream<Integer> stream=list.stream();
        boolean b=stream.noneMatch(t -> t>2);
        System.out.println(b);
        System.out.println("-----------分割线-------");

        stream=list.stream();
        b=stream.noneMatch(t -> t>5);
        System.out.println(b);

    }

运行结果为

false
-----------分割线-------
true

findFirst:返回最后一个元素,不过其返回的是一个Optional类

findAny:返回当前流中的任意元素,不过其返回的是一个Optional类

public static void main(String[] args) {
    List<Integer> list=Arrays.asList(1,3,2);
    Stream<Integer> stream=list.stream();
    Optional<Integer> OP=stream.findFirst();
    System.out.println(OP.get());
    System.out.println("-----------分割线-------");

    stream=list.stream();
    OP=stream.findAny();
    System.out.println(OP.get());

}

运行结果是

1
-----------分割线-------
1

整体demo实例:
allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false
noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false
anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false
findFirst:返回流中第一个元素
findAny:返回流中的任意元素
count:返回流中元素的总个数
max:返回流中元素最大值
min:返回流中元素最小值

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);  

boolean allMatch = list.stream().allMatch(e -> e > 10); //false
boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true
boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true 

Integer findFirst = list.stream().findFirst().get(); //1
Integer findAny = list.stream().findAny().get(); //1 

long count = list.stream().count(); //5
Integer max = list.stream().max(Integer::compareTo).get(); //5
Integer min = list.stream().min(Integer::compareTo).get(); //1

归约

方法作用
reduce(T identity, BinaryOperator accumulator)可以将流中元素反复结合起来,得到一个值,返回T(interface BinaryOperator extends BiFunction<T,T,T>)
reduce( BinaryOperator accumulator)可以将流中元素反复结合起来,得到一个值,返回 Optional
public static void main(String[] args) {
        List<Integer> list=Arrays.asList(1,3,2);
        // 把list中的值累加起来
        Stream<Integer> stream=list.stream();
        //为了方便理解 把这个初始值先写出来
        Integer start=0;
        Integer sum=stream.reduce(start, Integer::sum);
        System.out.println(sum);
        System.out.println("-----------分割线-------");
        stream=list.stream();
        start=1;
        sum=stream.reduce(start, Integer::sum);
        System.out.println(sum);
    }

运行结果是

6
-----------分割线-------
7

收集

collect:接收一个Collector实例,将流中元素收集成另外一个数据结构。

Collector<T, A, R> 是一个接口,有以下5个抽象方法:

Supplier < A>supplier():创建一个结果容器A
BiConsumer<A, T> accumulator():消费型接口,第一个参数为容器A,第二个参数为流中元素T。
BinaryOperator< A> combiner():函数接口,该参数的作用跟上一个方法(reduce)中的combiner参数一样,将并行流中各 个子进程的运行结果(accumulator函数操作后的容器A)进行合并。
Function<A, R> finisher():函数式接口,参数为:容器A,返回类型为:collect方法最终想要的结果R。
Set characteristics():返回一个不可变的Set集合,用来表明该Collector的特征。有以下三个特征:
CONCURRENT:表示此收集器支持并发。
UNORDERED:表示该收集操作不会保留流中元素原有的顺序。
IDENTITY_FINISH:表示finisher参数只是标识而已,可忽略。

public static void main(String[] args) {
        List<Integer> list=Arrays.asList(1,3,2);
        // 把list中的值累加起来
        Stream<Integer> stream=list.stream();

        Stream<Integer> stream1 =stream.filter(t-> t>1);
        System.out.println(stream1);
        System.out.println(stream1.collect(Collectors.toList())); //将 stream转换为一个list
        
    }

运行结果

java.util.stream.ReferencePipeline$2@254989ff
[3, 2]

方法集合

Person p1 = new Person("zhangsan",26);
Person p2 = new Person("lisi",22);
Person p3 = new Person("wangwu",23);
List<Person> list = Arrays.asList(p1,p2,p3);
//装成list
List<Integer> ageList = list.stream().map(Person::getAge).collect(Collectors.toList());//[26,22,22]
//转成set
Set<Integer> ageSet = list.stream().map(Person::getAge).collect(Collectors.toSet());//[26,22]

//转成map,注:key不能相同,否则报错
Map<String, Integer> studentMap = list.stream().collect(Collectors.toMap(Person::getName, Person::getAge)); 
// {zhangsan=26, lisi=22, wangwu=22}

//字符串分隔符连接
String joinName = list.stream().map(Person::getName).collect(Collectors.joining(",", "(", ")")); 
// (zhangsan,lisi,wangwu)

//聚合操作
//1.总数
Long count = list.stream().collect(Collectors.counting()); // 3
//2.最大年龄 (最小的minBy同理)
Integer maxAge = list.stream().map(Person::getAge).collect(Collectors.maxBy(Integer::compare)).get(); // 26
//3.所有人的年龄求和
Integer sumAge = list.stream().collect(Collectors.summingInt(Person::getAge)); // 70
//4.平均年龄
Double averageAge = list.stream().collect(Collectors.averagingDouble(Person::getAge)); // 23.333333333333332
// 带上以上所有方法
DoubleSummaryStatistics statistics = list.stream().collect(Collectors.summarizingDouble(Person::getAge));
System.out.println("count:" + statistics.getCount() + ",max:" + statistics.getMax() + ",sum:" + statistics.getSum() + ",average:" + statistics.getAverage());
        
//分组 按年龄分组
Map<Integer, List<Person>> ageMap = list.stream().collect(Collectors.groupingBy(Person::getAge));
//分区
//分成两部分,一部分大于10岁,一部分小于等于10岁
Map<Boolean, List<Person>> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));
//规约
Integer allAge = list.stream().map(Person::getAge).collect(Collectors.reducing(Integer::sum)).get(); //40 

常见方法

排序操作 将空数据排序到最后
//根据age正序
Collections.sort(list, Comparator.comparing(Student::getAge, Comparator.nullsLast(Intrger::compareTo)));
//根据age倒序
Collections.sort(list, Comparator.comparing(BondBsInfoListVo::getCompanyRank, Comparator.nullsLast(Intrger::compareTo)).reversed());

分组操作
//根据name进行分组
Map<String, List<Student>> studentMap = new HashMap<>();
list.stream().collect(Collectors.groupingBy(Student::getName)).forEach(
                    (name, newList) -> {
                        studentMap .put(name, newList);
                    }
            );

skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream, 如果原Stream中包含的元素个数小于N,那么返回空Stream;
 
list.stream().skip(index).collect(Collectors.toList());

limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;
 
list.stream().limit(index).collect(Collectors.toList());

分页操作
int pageNo = 1;//当前页数
int pageNo = 20;//每页显示条数
int start = (pageNo - 1) * pageSize;
list = list.stream().skip(start).collect(Collectors.toList());
list = list.stream().limit(pageSize).collect(Collectors.toList());

filter:过滤;
 
过滤出年龄大于19的人:
 
list.stream().filter(person -> (person.getAge() > 19)).collect(Collectors.toList());

map: 对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。这个方法有三个对于原始类型的变种方法,分别是:mapToInt,mapToLong和mapToDouble。这三个方法也比较好理解,比如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型。之所以会有这样三个变种方法,可以免除自动装箱/拆箱的额外消耗;
 
List<Student> students =
list.stream().map(person -> new Student(person.getName(), person.getAge())).collect(Collectors.toList());
 
List<String> names = list.stream().map(Person::getName).collect(Collectors.toList());
 
int[] ages = list.stream().mapToInt(Person::getAge).toArray();

累加、最大值、最小值、平均值等

//Integer
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(7);
list.add(2);
IntSummaryStatistics collect = list.stream().map(Student::getAge).collect(Collectors.summarizingInt(value -> value));
System.out.println(collect);
System.out.println("统计集合元素的个数:" + collect.getCount());
System.out.println("集合元素累加之和:" + collect.getSum());
System.out.println("集合中最小值:" + collect.getMax());
System.out.println("集合中最大值:" + collect.getMin());
System.out.println("集合中平均值:" + collect.getAverage());
打印结果:IntSummaryStatistics{count=3, sum=12, min=2, average=4.000000, max=7}
统计集合元素的个数:3
集合元素累加之和:12
集合中最小值:7
集合中最大值:2
集合中平均值:4.0


//BigDecimal   假设Person中age为BigDecimal类型
Person p1 = new Person("张三", new BigDecimal("11.0"));
Person p2 = new Person("王五", new BigDecimal("10.0"));
Person p3 = new Person("李四", new BigDecimal("9.0"));
Person p4 = new Person("王五", new BigDecimal("10.0"));
Person p5 = new Person("赵六", new BigDecimal("10.0"));
List<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
BigDecimal sum = list.stream().map(Person::getAge).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal max = list.stream().map(Person::getAge).reduce(BigDecimal.ZERO, BigDecimal::max);
BigDecimal min = list.stream().map(Person::getAge).reduce(BigDecimal.ZERO, BigDecimal::min);
System.out.println("年龄总计:" + sum);
System.out.println("年龄最大:" + max);
System.out.println("年龄最小:" + min);

打印结果:
年龄总计:50.0
年龄最大:11.0
年龄最小:9.0

多条件排序:
//先根据age排序 在根据name排序   
list.sort(Comparator.comparing(Person::getAge).thenComparing(Person::getName));

count:计数;
 
统计年龄大于19的人的数量:
 
long count = list.stream().filter(person -> (person.getAge() > 19)).count();

字段运算或求值
//int
list.stream().mapToInt(Person::getAge).sum();
list.stream().mapToInt(Person::getAge).max();
list.stream().mapToInt(Person::getAge).min();
list.stream().mapToInt(Person::getAge).average();
//double
list.stream().mapToDouble(Person::getAge).sum()//和
list.stream().mapToDouble(Person::getAge).max()//最大
list.stream().mapToDouble(Person::getAge).min()//最小
list.stream().mapToDouble(Person::getAge).average()//平均值

map.entrySet().removeIf(entry -> entry.getValue() == null);

举报

相关推荐

0 条评论