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

2025-05-14 12:02:04 144
魁首哥

在 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 uniquelist = arrays.stream(people)
        .distinct()
        .collect(collectors.tolist());

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

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

(1) 使用collectors.tomap

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

list 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 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 seenids = concurrenthashmap.newkeyset();
list uniquelist = arrays.stream(people)
        .filter(p -> seenids.add(p.getid())) // 若 id 未出现过,保留
        .collect(collectors.tolist());

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

list uniquelist = arrays.stream(people)
        .collect(collectors.tomap(
                person::getid,
                p -> p,
                (oldvalue, newvalue) -> newvalue // 冲突时保留新元素
        ))
        .values()
        .stream()
        .collect(collectors.tolist());

总结回答

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

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

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

分享
海报
144
上一篇:idea中使用git插件回滚代码的流程步骤 下一篇:SpringMVC获取请求参数的方法

忘记密码?

图形验证码