何种情况下交换a、b添加顺序后hashSet.size()为2而非3?
问题拆解与解答
嘿,这个问题挺有意思的,咱们一步步理清楚:要让交换add(a)和add(b)的顺序后,HashSet的大小从3变成2,核心得抓住HashSet的本质——它靠元素的hashCode()和equals()方法判断是否重复,而且如果元素的属性(影响这两个方法的)在添加过程中发生变化,就会搞出“顺序影响结果”的情况。
具体得满足这几个条件:
- 初始状态下,
a、b、c三个对象两两都不“相等”(也就是a.equals(b)、a.equals(c)、b.equals(c)全返回false),所以原顺序添加后集合能装下3个元素,size是3。 a的equals()或者hashCode()逻辑依赖某个可变属性,而且这个属性会被b的添加操作(或者b本身的存在)给修改。- 当先加
b再加a时,a的那个可变属性已经被修改了,导致此时a和b被判定为“相等”(哈希值相同且equals返回true),所以加a的时候会被当成重复元素,集合不新增;而c还是和a、b都不相等,最后集合size就变成2了。
给你写个实际能跑的代码例子,一看就懂:
import java.util.HashSet; class ThirdPartyType { // 用一个共享计数器当可变属性 private static int sharedFlag = 0; private int id; public ThirdPartyType(int id) { this.id = id; } // 自定义equals:当flag为1时,id=1的a会和id=2的b判定为相等 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ThirdPartyType that = (ThirdPartyType) o; if (sharedFlag == 1 && this.id == 1 && that.id == 2) { return true; } return id == that.id; } // 自定义hashCode:flag为1时,a的哈希值和b一样 @Override public int hashCode() { if (sharedFlag == 1 && id == 1) { return 2; } return id; } // 模拟添加b时触发flag修改 public void triggerFlag() { if (id == 2) { sharedFlag = 1; } } } public class TestHashSet { public static void main(String[] args) { ThirdPartyType a = new ThirdPartyType(1); ThirdPartyType b = new ThirdPartyType(2); ThirdPartyType c = new ThirdPartyType(3); // 原顺序:先加a,再加b,最后加c HashSet<ThirdPartyType> originalSet = new HashSet<>(); originalSet.add(a); b.triggerFlag(); // 加b的时候改flag,但a已经加进去了,不影响之前的判断 originalSet.add(b); originalSet.add(c); System.out.println(originalSet.size()); // 输出3,因为加a的时候flag还是0,a和b不重复 // 交换顺序:先加b,再加a,最后加c ThirdPartyType.sharedFlag = 0; // 重置flag HashSet<ThirdPartyType> swappedSet = new HashSet<>(); b.triggerFlag(); // 先改flag,再把b加进去 swappedSet.add(b); swappedSet.add(a); // 此时a的哈希和b一样,equals也返回true,被判定为重复,加不进去 swappedSet.add(c); System.out.println(swappedSet.size()); // 输出2 } }
总结一下就是:后添加的对象会改变先添加对象的重复判断逻辑,但原顺序里先加的对象还没被修改,所以三个都能存;交换顺序后,先加的对象提前修改了逻辑,导致后面加的对象被当成重复的。
内容的提问来源于stack exchange,提问作者Руслан Сударев
相关产品推荐
相关产品推荐

