跳过正文
  1. 博客/
  2. 后端/
  3. 框架/

Stream源码(1):如何实现去重

3 分钟· ·
后端 框架 Java Stream
作者
Allen
一个强大、轻量级的 Hugo 主题。
目录

本篇博客是在看代码的时候看到使用Java8使用Stream去重的妙用,从而对Java如何使用Stream实现几行代码
完成一个可支持并行化的流式计算程序

引言
#

什么是Stream

简单来说Stream就是Java8引入的一种流式API,让只需要定义一些处理函数就能优雅的对集合的一些操作

举个栗子,之前我们想遍历打印所有的参数我们得写下面代码

    for (int i : new int[]{1, 2, 3, 4}) {
  
        System.out.println(i);
  
    }
  

假如使用Java8,我们只需要一行代码

    Arrays.stream(new int[]{1, 2, 3, 4}).forEach(System.out::println);
  

我们只需要定义一个函数,其他的Stream帮我们解决

Stream模型
#

简单来说Stream把操作分为两张,一种是中间操作,一种是终结操作

中间操作你可以把他看做对数据源的一种处理,而终结操作是定义产生新数据过程,简单来说,假如我们有一堆苹果
需要处理,我们使用一个流水线来对经过的苹果进行各种处理(中间操作),丢掉烂掉的(filter),削掉皮(map)等等,
最后的我们需要对苹果进行装箱(终结操作)

分析功能
#

我们接下来看看我们需要实现的功能,就是去重,我们知道Stream其实提供了一个distinct方法中间操作来帮我们实现去重功能,
对于基本类型比如StringIntegerLong这些我们能很容易进行去重,但是对于复杂类,我们得
重写hashCodeequal方法来支持去重操作了,对于集合内的每个数据都会用equal来进行去重

接下来我们尝试直接使用终结操作collect来解决掉
怎么做呢,collect其实也很简单就是创建一个容器,把数据装进去,我们就只需要使用一个可以支持去重操作的
容器来做就好了

支持去重的有MapSet,所以我们想到的第一个方法就是将流变成一个Set,这个也是网上很多人提供的一个版本

dishes.stream().distinct().collect(Collectors.toCollection(
  
            () -> new TreeSet<>(Comparator.comparing(Dish::getType)))
  

我们把这行代码给分解成两行

    TreeSet<Dish> container = new TreeSet<>(Comparator.comparing(Dish::getType));
  
    dishes.stream().collect(Collectors.toCollection(() -> container));
  

第一行其实就是声明了一个容器,核心代码就是 () -> container 我们传入一个容器,让他来存贮,我们使用
TreeSet的一个构造器,它只需要传入一个函数,他会比较传进来的每个值,假如发现已经存在了它就不会插入了

但是这个有个问题就是,他只能选择第一个出现的

接下来我们试试用Map

    dishes.stream().collect(toMap(Dish::getType, d -> d);
  

我们写下下面的代码,但是这个代码有点问题就是假如出现重复的,他会抛异常,因为程序默认不知道你想要哪个数据

    dishes.stream().collect(toMap(Dish::getType, d -> d, (oldData, newData) -> oldData));
  

我们可以传入一个选择函数,这样当发现重复的时候就可以选择要哪个插入到map中去,这个也解决了上面使用Set来存贮的时候没法选择到底是新来的还是后来的

总结
#

这篇博客简单的介绍了实现去重功能的三种实现方法,接下来这个系列的博客会深入到源码来探究Java8如何实现
Stream这么多功能的

引用
#

相关文章

Java的char类型到底几个字节
6 分钟
后端 框架 Java
Dubbo浅探
3 分钟
后端 框架 Java Dubbo
Spring Cloud Alibaba浅探
2 分钟
后端 框架 Java SpringBoot
SpringCloud浅析
5 分钟
后端 框架 Java SpringBoot
如何在Ubuntu上发布Scala Jar包到Maven中央仓库
7 分钟
后端 框架 Java
浅析Spring
3 分钟
后端 框架 Java SpringBoot