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

Java中Set如何比较对象?数组与List存入Set的差异解析

Java中Set的对象重复判定逻辑及数组与List的equals差异

一、Set判断对象重复的核心规则

以常用的HashSet为例,它判定元素重复的逻辑是先比较哈希码,再用equals确认:

  1. 向Set添加元素时,先调用元素的hashCode()计算哈希值;
  2. 若哈希值对应桶中无元素,直接添加;
  3. 若桶中有元素,会调用equals()与桶内元素逐一比较:
    • 若equals()返回true,判定为重复元素,不添加;
    • 若equals()返回false,视为不同元素,添加到桶中。
      所有Set实现类的重复判定都依赖hashCode()和equals(),仅不同Set的哈希/比较细节有差异(比如TreeSet用Comparable或Comparator,但本质还是基于自定义相等逻辑)。

二、数组与List的equals差异(结合你的代码示例)

1. 数组的equals行为

你的第一段代码:

int[] arr1 = new int[] {1, 2};
int[] arr2 = new int[] {1, 2};
if (arr1 == arr2) {
   // 不会被打印
   System.out.println("hello");
}
Set<int[]> set1 = new HashSet<>();
set1.add(arr1);
set1.add(arr2);
System.out.println(set1.size()); // 输出2

数组作为Java原生对象,equals()方法继承自Object,默认比较对象的引用地址(和==逻辑完全一致)。因此arr1.equals(arr2)返回false,hashCode()也基于引用地址计算,两个数组哈希值不同,HashSet会将它们视为不同元素,最终size为2。

若要比较数组内容是否相同,需使用Arrays.equals(arr1, arr2)方法,该方法会逐一比较数组元素值。

2. List的equals行为

你的第二段代码:

Set<List<Integer>> set = new HashSet<>();
List<Integer> list1 = Arrays.asList(1, 2, 3, 4);
List<Integer> list2 = Arrays.asList(1, 2, 3, 4);
set.add(list1);
set.add(list2);
if (list1 == list2) {
   // 不会被打印
   System.out.println("hello");
}
System.out.println(set); // 输出[[1, 2, 3, 4]]
System.out.println(set.size()); // 输出1

Arrays.asList()返回的java.util.Arrays.ArrayList(Java内置List实现类)重写了hashCode()和equals():

  • equals()会遍历两个List的元素,逐一调用元素的equals()比较,仅当元素数量、顺序、对应位置元素均相等时返回true;
  • hashCode()基于所有元素的哈希值计算得出。
    因此list1.equals(list2)返回true,且两者hashCode()相等,HashSet判定为重复元素,最终仅保留一个,size为1。

三、其他数据结构存入Set的重复判定逻辑

判断任意数据结构存入Set时是否视为重复,核心看两点:

  1. 该数据结构是否重写了hashCode()和equals()方法;
  2. 这两个方法的实现逻辑是否符合“内容相等则判定为重复”的预期。

常见例子:

  • 自定义类:未重写时默认用Object的引用比较逻辑,即使内容一致也会被Set视为不同元素;重写后则按自定义规则判断(比如基于类的核心字段比较)。
  • String:已重写hashCode()和equals(),基于字符序列比较,内容相同的String存入Set仅保留一个。
  • HashMap:重写了hashCode()和equals(),比较逻辑为:两个Map的键值对数量相同,且每个键值对的键、值分别相等(键用equals,值用equals),则视为相等。内容相同的HashMap存入Set会被判定为重复。
  • TreeSet:不依赖hashCode()和equals(),而是基于元素的Comparable实现或构造时传入的Comparator,只要比较器认为两个元素“相等”(compare()返回0),就会被视为重复。

关键原则:始终保证hashCode()和equals()的一致性——若两个对象equals()返回true,它们的hashCode()必须相等;反之,hashCode()相等的对象,equals()不一定必须true(但会影响HashSet性能)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:17:40