java使用Stream流对自定义对象数组去重的实现

 更新时间:2025年04月16日 10:54:35   作者:Aaron Fang  
本文主要介绍了java使用Stream流对自定义对象数组去重的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在 Java 中,使用 Stream 流对自定义对象数组去重的核心是确保对象能正确判断“重复”的逻辑。以下是具体实现方法及场景分析:

方法 1:直接使用 distinct()(需重写 equals 和 hashCode)

若自定义对象已正确重写 equals() 和 hashCode() 方法,可直接通过 distinct() 去重。
适用场景:对象的唯一性由所有字段共同决定(如数据库实体类的主键)。

示例代码

public class Person {
    private String id;
    private String name;

    // 构造方法、Getter/Setter 省略

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(id, person.id); // 根据 id 判断是否相等
    }

    @Override
    public int hashCode() {
        return Objects.hash(id); // 基于 id 生成哈希
    }
}

// 使用 Stream 去重
Person[] people = ...; // 自定义对象数组
List<Person> uniqueList = Arrays.stream(people)
        .distinct()
        .collect(Collectors.toList());

方法 2:基于对象的某个唯一属性去重(无需重写 equals 和 hashCode)

若无法修改对象类(如第三方库的类),或需根据部分字段去重,可用 Collectors.toMap 或 TreeSet 实现。

(1) 使用 Collectors.toMap

适用场景:根据唯一键(如 id)去重,保留第一个出现的元素。

List<Person> uniqueList = Arrays.stream(people)
        .collect(Collectors.toMap(
                Person::getId, // Key 提取函数(根据 id 去重)
                p -> p,       // Value 为对象本身
                (existing, replacement) -> existing // 冲突时保留已存在的元素
        ))
        .values()            // 获取去重后的 Value 集合
        .stream()
        .collect(Collectors.toList());

(2) 使用 TreeSet 自定义比较器

适用场景:需要根据多个字段去重,或动态指定去重规则。

List<Person> uniqueList = Arrays.stream(people)
        .collect(Collectors.toCollection(
            () -> new TreeSet<>(Comparator.comparing(p -> p.getId() + p.getName()))
        ))
        .stream()
        .collect(Collectors.toList());

方法 3:使用 filter + 内存状态去重

适用场景:需根据动态条件去重(如去重后保留最后一个元素)。

(1) 使用 ConcurrentHashMap 维护状态

Set<String> seenIds = ConcurrentHashMap.newKeySet();
List<Person> uniqueList = Arrays.stream(people)
        .filter(p -> seenIds.add(p.getId())) // 若 id 未出现过,保留
        .collect(Collectors.toList());

(2) 保留最后一个出现的元素

List<Person> uniqueList = Arrays.stream(people)
        .collect(Collectors.toMap(
                Person::getId,
                p -> p,
                (oldValue, newValue) -> newValue // 冲突时保留新元素
        ))
        .values()
        .stream()
        .collect(Collectors.toList());

总结回答

  • 直接去重:若对象重写了 equals() 和 hashCode(),直接用 distinct()
  • 按属性去重:使用 Collectors.toMap 或 TreeSet,根据唯一键(如 id)过滤。
  • 动态去重:通过 filter 配合内存集合(如 ConcurrentHashMap)控制去重逻辑。

关键点:明确业务中“重复”的定义(如全字段相等或部分字段相等),选择性能与代码简洁性兼顾的方案。

到此这篇关于java使用Stream流对自定义对象数组去重的实现的文章就介绍到这了,更多相关java 自定义对象数组去重内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring中常用注解的用法

    Spring中常用注解的用法

    这篇文章主要介绍了Spring中常用注解的用法,Spring注解方式减少了配置文件内容,更加便于管理,并且使用注解可以大大提高了开发效率,注解本身是没有功能的,和xml一样,注解和xml都是一种元数据,元数据即解释数据的数据,也就是所谓的配置,需要的朋友可以参考下
    2023-08-08
  • MybatisX中xml映射文件中命名空间爆红的解决

    MybatisX中xml映射文件中命名空间爆红的解决

    本文主要介绍了MybatisX中xml映射文件中命名空间爆红的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • SpringBoot中使用@Async注解失效场景及说明

    SpringBoot中使用@Async注解失效场景及说明

    在Spring Boot中,@Async注解就像一把刀,能帮你轻松处理那些耗时的任务,让主线程可以继续忙别的事儿,不过,跟所有强大的工具一样,用不好它也可能出岔子,为了避免这些坑,咱们得深入了解下@Async注解,接下来,咱们就来聊聊7种常见的@Async失效情况,需要的朋友可以参考下
    2024-07-07
  • 在Java中将double转换为int的操作方法

    在Java中将double转换为int的操作方法

    这篇文章主要介绍了在Java中将double转换为int的操作方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java中lambda表达式的基本运用

    Java中lambda表达式的基本运用

    大家好,本篇文章主要讲的是Java中lambda表达式的基本运用,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Java8 接口默认方法和静态方法

    Java8 接口默认方法和静态方法

    这篇文章主要介绍了Java8 接口默认方法和静态方法,在默认接口中使用关键字default声明并提供具体实现,而且该方法不需要添加public关键字就可以公开调用,甚至你可以在其实现类中覆写,带着对默认接口的方法和小编一起探索下面文章内容的静态方法吧
    2021-10-10
  • Java的方法详解

    Java的方法详解

    方法类似于C语言中的函数,是包含特定功能的代码块,必须定义在类中、main方法外部,本质上是一个造轮子的过程—— 将重复使用的逻辑包装成方法,需要时直接调用,无需重复编写,下面通过示例详解Java的方法,感兴趣的朋友一起看看吧
    2026-02-02
  • Java用GDAL读写shapefile的方法示例

    Java用GDAL读写shapefile的方法示例

    Shapefile文件是描述空间数据的几何和属性特征的非拓扑实体矢量数据结构的一种格式,由ESRI公司开发。这篇文章给大家介绍了Java如何用GDAL读写shapefile的方法示例,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • JVM加载class文件的原理机制实例详解

    JVM加载class文件的原理机制实例详解

    Java是一种具有动态性的解释型语言,类(class)只有被加载到JVM后才能运行,接下来通过本文给大家介绍JVM加载class文件的原理机制详解,感兴趣的朋友一起看看吧
    2022-04-04
  • 利用Java编写一个出敬业福的小程序

    利用Java编写一个出敬业福的小程序

    新年将至,又开始扫福活动,每年的敬业福成了大家难过的坎。所以本文将介绍一个通过Java编写的一款福字生成器,感兴趣的小伙伴可以试一试
    2022-01-01

最新评论