You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java HashSet contains方法异常:应为false却返回true

问题根源与修复方案

核心问题

你的代码出现结果不一致的原因在于Triple类的equals方法违反了Java中equals约定的对称性原则,同时缺少必要的类型检查:

  1. 对称性破坏:

    • 当HashSet执行contains(triple2)时,实际是用triple2.equals(triple1)来判断。此时triple2的equals方法会检查triple1的列表是否包含triple2的所有元素(0、0、0),triple1的列表[-4,0,4]包含0,所以返回true。
    • 而Objects.equals(triple1, triple2)是调用triple1.equals(triple2),此时会检查triple2的列表是否包含triple1的所有元素(-4、0、4),triple2的列表[0,0,0]不包含-4和4,所以返回false。
      这就导致两种判断逻辑的结果完全相反。
  2. 缺少类型检查:如果向equals方法传入非Triple类型的对象,会直接抛出ClassCastException,不符合equals方法的规范。

  3. equals逻辑不符合预期:当前用contains判断元素存在的逻辑,无法区分元素数量和顺序,比如Triple(0,1,1).equals(Triple(0,0,0))会返回true,这显然不是合理的相等判断。

修复方案

根据你的实际需求,提供两种修复方式:

需求1:三元组元素顺序一致时判定相等

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

class Triple {
    private final List<Integer> triple;

    public Triple(int one, int two, int three) {
        this.triple = new ArrayList<>();
        this.triple.add(one);
        this.triple.add(two);
        this.triple.add(three);
    }

    @Override
    public int hashCode() {
        // 使用Objects.hash生成低冲突的哈希值
        return Objects.hash(triple.get(0), triple.get(1), triple.get(2));
    }

    @Override
    public boolean equals(Object o) {
        // 引用直接相等,返回true
        if (this == o) return true;
        // 类型不符或为空,返回false
        if (o == null || getClass() != o.getClass()) return false;
        Triple other = (Triple) o;
        // 利用List的equals方法按顺序比较元素
        return triple.equals(other.triple);
    }
}

需求2:三元组元素相同(不考虑顺序,需匹配重复次数)时判定相等

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

class Triple {
    private final List<Integer> triple;
    // 缓存排序后的列表,避免每次equals都重复排序
    private final List<Integer> sortedTriple;

    public Triple(int one, int two, int three) {
        this.triple = new ArrayList<>();
        this.triple.add(one);
        this.triple.add(two);
        this.triple.add(three);
        this.sortedTriple = new ArrayList<>(triple);
        Collections.sort(sortedTriple);
    }

    @Override
    public int hashCode() {
        // 基于排序后的列表生成哈希值,保证相等对象的哈希值一致
        return Objects.hash(sortedTriple.get(0), sortedTriple.get(1), sortedTriple.get(2));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Triple other = (Triple) o;
        // 比较排序后的列表,忽略原始顺序
        return sortedTriple.equals(other.sortedTriple);
    }
}

修复后效果

修复后的代码满足Java的equals/hashCode约定:

  • equals方法具备对称性、自反性和传递性;
  • hashCode与equals逻辑一致,相等的对象哈希值一定相等;
  • HashSet的contains方法与Objects.equals的结果会完全一致。

内容的提问来源于stack exchange,提问作者andrew_lau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:12:47