Jdk8,Stream流:常用方法,玩转集合操作

Jdk8,Stream流:常用方法,玩转集合操作

  • 前提
    • 需要了解@FunctionalInterface:函数式接口,很多方法参数都是函数式接口,需要了解的可以看下这篇文章
  • 数据转换
    • 1:转数组
    • 2:转Set
    • 3:转Collection
    • 4:转Map(详细操作请看:[Jdk8,Stream流collect方法:让集合操作如此简单(数据转化,分组GroupBy,统计和复杂操作)](https://blog.csdn.net/weixin_43938143/article/details/122802389?spm=1001.2014.3001.5501))
  • 数据处理
    • 1:多功能超强处理collect(详细操作请看:[Jdk8,Stream流collect方法:让集合操作如此简单(数据转化,分组GroupBy,统计和复杂操作)](https://blog.csdn.net/weixin_43938143/article/details/122802389?spm=1001.2014.3001.5501))
      • 1.分组
      • 2:组合统计
    • 2:遍历处理
      • 1.map,flatMap
      • 2:mapToInt,mapToInt,mapToDouble
      • 3:peek
    • 3:过滤
    • 4:匹配判断
      • 1:全部都匹配
      • 2:某一个匹配
      • 3:都不匹配
    • 5:获取集合元素
      • 1:获取第一个
      • 2:获取任意一个
    • 6:截取
      • 1:顺序截取
      • 2:跳过截取
    • 7:去重
    • 8:排序
      • 1:最大值
      • 2:最小值
      • 3:默认排序
      • 4:Comparator排序
    • 9:聚合操作
      • 1:基础聚合
      • 2:指定初始值聚合
      • 3:并发聚合
    • 10:并发操作
      • 1:直接使用parallelStream流
      • 2:普通流转并发流
      • 3:并发流转普通流
      • 4:判断是否并发流
      • 5:并发按顺序遍历
    • 10:关闭流
    • 1:onClose
    • 2:close

前提

需要了解@FunctionalInterface:函数式接口,很多方法参数都是函数式接口,需要了解的可以看下这篇文章

Jdk8,@FunctionalInterface:函数式接口,学会使用lamda表达式,通俗易懂

比如转化Map的toMap方法
在这里插入图片描述
比如对集合分组的groupingBy方法
在这里插入图片描述
比如获取最大值的maxBy方法
在这里插入图片描述

数据转换

1:转数组

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void toArray() {
        Object[] result = list.stream().toArray();
        Arrays.stream(result).forEach(System.out::print);
    }
    
	@Test
    public void toArrayWithGenerator() {
        Integer[] result = list.stream().toArray(t -> new Integer[list.size()]);
        Arrays.stream(result).forEach(System.out::print);
    }

输出:两种方式,不加参数返回的是:Object[],加参数可以指定数组的类型,比如例子中的:Integer[]

52416310879
52416310879

2:转Set

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void toSet() {
        Set<Integer> collect = list.stream().collect(Collectors.toSet());
        System.out.println("collect = " + collect);
    }

输出

collect = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

3:转Collection

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void toCollection() {
        Set<Integer> collect = list.stream().collect(Collectors.toCollection(TreeSet::new));
        System.out.println("collect.getClass().getName() = " + collect.getClass().getName());
    }

输出:将List转成了TreeSet

collect.getClass().getName() = java.util.TreeSet

4:转Map(详细操作请看:Jdk8,Stream流collect方法:让集合操作如此简单(数据转化,分组GroupBy,统计和复杂操作))

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void toMap() {
        Map<Integer, Integer> collect = list.stream().collect(Collectors.toMap(Function.identity(), v -> v * 10));
        System.out.println("collect = " + collect);
    }

输出:key为对象自身,value为对象自身 * 10

collect = {1=10, 2=20, 3=30, 4=40, 5=50, 6=60, 7=70, 8=80, 9=90, 10=100}

数据处理

1:多功能超强处理collect(详细操作请看:Jdk8,Stream流collect方法:让集合操作如此简单(数据转化,分组GroupBy,统计和复杂操作))

1.分组

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void groupingBy() {
        Map<Integer, List<Integer>> collect = list.stream().collect(Collectors.groupingBy(k -> k % 2));
        System.out.println("collect = " + collect);
    }

输出:根据除以2的余数进行分组,共两组,key为0和1

collect = {0=[2, 4, 6, 10, 8], 1=[5, 1, 3, 7, 9]}

2:组合统计

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void summarizingInt() {
        IntSummaryStatistics collect = list.stream().collect(Collectors.summarizingInt(t -> t));
        System.out.println("collect = " + collect);
    }

输出:统计出数量,和,最小值,平均数,最大值

collect = IntSummaryStatistics{count=10, sum=55, min=1, average=5.500000, max=10}

2:遍历处理

1.map,flatMap

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void map() {
        List<Integer> result = list.stream().map(t -> t * 10).collect(Collectors.toList());
        System.out.println("result = " + result);
    }

    @Test
    public void flatMap() {
        List<Integer> result = list.stream().flatMap(t -> Stream.of(t * 10)).collect(Collectors.toList());
        System.out.println("result = " + result);
    }

类似遍历的forEach,因为使用参数(Function,Consumer)不同,导致返回值类型不同
在这里插入图片描述

都是遍历处理,区别在于返回值类型
在这里插入图片描述
输出:

result = [50, 20, 40, 10, 60, 30, 100, 80, 70, 90]
result = [50, 20, 40, 10, 60, 30, 100, 80, 70, 90]

2:mapToInt,mapToInt,mapToDouble

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void mapToInt() {
        list.stream().mapToInt(t -> t * 10).forEach(System.out::print);
    }

    @Test
    public void mapToLong() {
        list.stream().mapToLong(t -> t * 10).forEach(System.out::print);
    }

    @Test
    public void mapToDouble() {
        list.stream().mapToDouble(t -> t * 10).forEach(System.out::println);
    }

输出:返回值类型不同,分别为Int,Long,Double

502040106030100807090
502040106030100807090

50.0
20.0
40.0
10.0
60.0
30.0
100.0
80.0
70.0
90.0

3:peek

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void peek() {
        List<Integer> result = list.stream().peek(System.out::print).collect(Collectors.toList());
        System.out.println("result = " + result);
    }

类似遍历的forEach,参数都一样:Consumer,区别在于返回值
在这里插入图片描述

输出:

52416310879
result = [5, 2, 4, 1, 6, 3, 10, 8, 7, 9]

3:过滤

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void filter() {
        List<Integer> result = list.stream().filter(t -> t % 2 == 0).collect(Collectors.toList());
        System.out.println("result = " + result);
    }

输出:根据是否为偶数进行过滤

result = [2, 4, 6, 10, 8]

4:匹配判断

1:全部都匹配

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void allMatch() {
        boolean result = list.stream().allMatch(t -> t % 2 == 0);
        System.out.println("result = " + result);
    }

输出:是否都是偶数

result = false

2:某一个匹配

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void anyMatch() {
        boolean result = list.stream().anyMatch(t -> t % 2 == 0);
        System.out.println("result = " + result);
    }

输出:是否有一个元素为偶数

result = true

3:都不匹配

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void noneMatch() {
        boolean result = list.stream().noneMatch(t -> t % 2 == 0);
        System.out.println("result = " + result);
    }

输出:是否都不是偶数

result = false

5:获取集合元素

1:获取第一个

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void findFirst() {
        Optional<Integer> result = list.stream().findFirst();
        System.out.println("result = " + result);
    }

输出:返回值类型为Optional Jdk8,Optional类:简化代码,告别空指针NullPointerException

result = Optional[5]

2:获取任意一个

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void findAny() {
        Optional<Integer> result = list.stream().findAny();
        System.out.println("result = " + result);
    }

输出:返回值类型为Optional Jdk8,Optional类:简化代码,告别空指针NullPointerException

result = Optional[5]

6:截取

1:顺序截取

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void limit() {
        List<Integer> result = list.stream().limit(2).collect(Collectors.toList());
        System.out.println("result = " + result);
    }

输出:截取前两个

result = [5, 2]

2:跳过截取

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void skip() {
        List<Integer> result = list.stream().skip(2).collect(Collectors.toList());
        System.out.println("result = " + result);
    }

输出:跳过前两个元素

result = [4, 1, 6, 3, 10, 8, 7, 9]

7:去重

	private List<Integer> list = Arrays.asList(5, 5, 5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void distinct() {
        List<Integer> result = list.stream().distinct().collect(Collectors.toList());
        System.out.println("result = " + result);
    }

输出:

result = [5, 2, 4, 1, 6, 3, 10, 8, 7, 9]

8:排序

1:最大值

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void max() {
        Optional<Integer> result = list.stream().max(Comparator.naturalOrder());
        System.out.println("result = " + result);
    }

输出:

result = Optional[10]

2:最小值

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void min() {
        Optional<Integer> result = list.stream().min(Comparator.naturalOrder());
        System.out.println("result = " + result);
    }

输出:

result = Optional[1]

3:默认排序

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void sorted() {
        List<Integer> result = list.stream().sorted().collect(Collectors.toList());
        System.out.println("result = " + result);
    }

输出:

result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

4:Comparator排序

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void sortedWith() {
        List<Integer> result1 = list.stream().sorted(Comparator.naturalOrder()).collect(Collectors.toList());
        System.out.println("result1 = " + result1);
        List<Integer> result2 = list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        System.out.println("result2 = " + result2);
    }

输出:

result1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

9:聚合操作

1:基础聚合

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void reducing() {
        Optional<Integer> result = list.stream().reduce((t, u) -> {
            System.out.println("t = " + t + ", u = " + u);
            System.out.println("-----------------------");
            return t - u;
        });
        System.out.println("result = " + result);
    }

输出:对集合元素进行累减,从第二个参数t可以看出, t为上一次操作的结果。在这里第一个t = 5,u = 2,t - u = 3赋值到第二个t,所以二个t = 3

t = 5, u = 2
-----------------------
t = 3, u = 4
-----------------------
t = -1, u = 1
-----------------------
t = -2, u = 6
-----------------------
t = -8, u = 3
-----------------------
t = -11, u = 10
-----------------------
t = -21, u = 8
-----------------------
t = -29, u = 7
-----------------------
t = -36, u = 9
-----------------------
result = Optional[-45]

2:指定初始值聚合

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void reducingWithIdentity() {
        Integer result = list.stream().reduce(100, (t, u) -> {
            System.out.println("t = " + t + ", u = " + u);
            System.out.println("-----------------------");
            return t - u;
        });
        System.out.println("result = " + result);
    }

输出:第一个参数t,跟上面例子对比,发现不是5,而是指定的初始值100

t = 100, u = 5
-----------------------
t = 95, u = 2
-----------------------
t = 93, u = 4
-----------------------
t = 89, u = 1
-----------------------
t = 88, u = 6
-----------------------
t = 82, u = 3
-----------------------
t = 79, u = 10
-----------------------
t = 69, u = 8
-----------------------
t = 61, u = 7
-----------------------
t = 54, u = 9
-----------------------
result = 45

3:并发聚合

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

   @Test
    public void reducingWithCombiner() {
        Integer result = list.parallelStream().reduce(100, (t, u) -> {
            System.out.println("t = " + t + ", u = " + u);
            System.out.println("-----------------------");
            return t - u;
        }, (t, u) -> {
            System.out.println("t = " + t + ", u = " + u);
            System.out.println("=======================");
            return t - u;
        });
        System.out.println("result = " + result);
    }

输出:

t = 100, u = 8
-----------------------
t = 100, u = 4
-----------------------
t = 100, u = 7
-----------------------
t = 100, u = 5
-----------------------
t = 100, u = 10
-----------------------
t = 100, u = 6
-----------------------
t = 100, u = 2
-----------------------
t = 100, u = 3
-----------------------
t = 95, u = 98
t = 100, u = 9
-----------------------
t = 100, u = 1
-----------------------
t = 93, u = 91
=======================
=======================
t = 97, u = 90
=======================
t = 92, u = 2
=======================
t = 99, u = 94
=======================
t = 7, u = 90
=======================
t = 96, u = 5
=======================
t = -3, u = 91
=======================
t = -94, u = -83
=======================
result = -11

10:并发操作

1:直接使用parallelStream流

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void parallelStream() {
        list.parallelStream().forEach(integer -> System.out.println("integer = " + integer + ",Thread.currentThread().getName() = " + Thread.currentThread().getName()));
    }

输出:可以看到主线程和ForkJoinPool的线程都参与了操作

integer = 2Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-3
integer = 7Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-2
integer = 5Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-3
integer = 6Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-5
integer = 8Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-4
integer = 4Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-1
integer = 10Thread.currentThread().getName() = main
integer = 1Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 3Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-6
integer = 9Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-2

2:普通流转并发流

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void parallel() {
        list.stream().parallel().forEach(integer -> System.out.println("integer = " + integer + ",Thread.currentThread().getName() = " + Thread.currentThread().getName()));
    }

输出:可以看到主线程和ForkJoinPool的线程都参与了操作

integer = 4Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-1
integer = 7Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-2
integer = 10Thread.currentThread().getName() = main
integer = 5Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-6
integer = 6Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-5
integer = 2Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-3
integer = 8Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-4
integer = 3Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-2
integer = 9Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 1Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-1

3:并发流转普通流

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void sequential() {
        list.parallelStream().sequential().forEach(integer -> System.out.println("integer = " + integer + ",Thread.currentThread().getName() = " + Thread.currentThread().getName()));
    }

输出:可以看到虽然使用了parallelStream,但是只有主线程参与了操作

integer = 5Thread.currentThread().getName() = main
integer = 2Thread.currentThread().getName() = main
integer = 4Thread.currentThread().getName() = main
integer = 1Thread.currentThread().getName() = main
integer = 6Thread.currentThread().getName() = main
integer = 3Thread.currentThread().getName() = main
integer = 10Thread.currentThread().getName() = main
integer = 8Thread.currentThread().getName() = main
integer = 7Thread.currentThread().getName() = main
integer = 9Thread.currentThread().getName() = main

4:判断是否并发流

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void isParallel() {
        System.out.println("list.stream().isParallel() = " + list.stream().isParallel());
        System.out.println("list.parallelStream().isParallel() = " + list.parallelStream().isParallel());
    }

输出:

list.stream().isParallel() = false
list.parallelStream().isParallel() = true

5:并发按顺序遍历

	private List<Integer> list = Arrays.asList(5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void forEachOrdered() {
        list.parallelStream().forEach(integer -> System.out.println("integer = " + integer + ",Thread.currentThread().getName() = " + Thread.currentThread().getName()));
        System.out.println("--------------------------------------------------------------------------------------------");
        list.parallelStream().forEachOrdered(integer -> System.out.println("integer = " + integer + ",Thread.currentThread().getName() = " + Thread.currentThread().getName()));
    }

输出:可以看到使用普通的foreach遍历,因为是多线程,所以是乱序的。但是使用forEachOrdered遍历的话,就会按集合原本顺序进行遍历

integer = 2Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-3
integer = 5Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-3
integer = 3Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-3
integer = 9Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-4
integer = 10Thread.currentThread().getName() = main
integer = 4Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-1
integer = 6Thread.currentThread().getName() = main
integer = 8Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-5
integer = 1Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-1
integer = 7Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-2
--------------------------------------------------------------------------------------------
integer = 5Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-4
integer = 2Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 4Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 1Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 6Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 3Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 10Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 8Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 7Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7
integer = 9Thread.currentThread().getName() = ForkJoinPool.commonPool-worker-7

10:关闭流

1:onClose

	private List<Integer> list = Arrays.asList(5, 5, 5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void onClose() {
        list.stream().onClose(() -> System.out.println("Collectors.toList()")).collect(Collectors.toList());
    }

输出:可以发现输出结果为空,并没有想象中打印"Collectors.toList()"


2:close

	private List<Integer> list = Arrays.asList(5, 5, 5, 2, 4, 1, 6, 3, 10, 8, 7, 9);

    @Test
    public void close() {
        list.stream().onClose(() -> System.out.println("Collectors.toList()")).close();
    }

输出:可以发现与上面不同,这次打印了 “Collectors.toList()” 。因为当使用close关闭流的时候,才会执行onClose里面定义的方法,需要进行配合使用

Collectors.toList()

你可能感兴趣的:(java,开发语言,后端)