集合分配律验证代码始终返回false问题排查求助
排查集合分配律验证返回false的问题
我来帮你一步步找出问题所在,你的代码里有几个关键错误导致结果不符合预期:
1. 复制构造函数重复添加元素
你的Set类复制构造函数犯了一个低级错误:先通过new ArrayList<>(otherSet.s)把所有元素复制到新集合,然后又循环遍历otherSet.s再添加一遍,这会导致每个元素都被重复插入。集合的核心特性是元素唯一,重复元素会直接干扰后续的交并运算和相等性判断。
修复后的复制构造函数:
public Set(Set otherSet) { // 直接通过ArrayList的复制构造函数完成元素拷贝,无需额外循环添加 this.s = new ArrayList<Zodiac>(otherSet.s); }
另外建议你在Set的add方法里添加重复检查,确保任何时候集合里都不会出现重复元素:
public boolean add(Zodiac z) { if (!s.contains(z)) { s.add(z); return true; } return false; }
2. 分配律右侧(RHS)的计算逻辑完全错误
你当前的RHS代码是:
setA2.union(setB2); setA2.union(setC2); setA2.intersection(setA2);
这实际上计算的是A ∪ B ∪ C(最后一步和自己交集等于自身),完全不符合分配律的(A ∪ B) ∩ (A ∪ C)。正确的做法应该是创建临时集合保存中间结果,避免修改原集合:
修复后的RHS计算代码:
// 计算 (A ∪ B) Set tempAB = new Set(setA2); tempAB.union(setB2); // 计算 (A ∪ C) Set tempAC = new Set(setA2); tempAC.union(setC2); // 计算两者的交集得到RHS Set rhs = new Set(tempAB); rhs.intersection(tempAC); System.out.printf("RHS analysis\n"); System.out.printf("\t RHS = {%s}%n", rhs);
3. 交并方法的实现需保证元素唯一性
如果你的union和intersection方法没有处理重复元素,也会导致结果异常。比如union方法应该只添加当前集合没有的元素,intersection方法应该移除不在另一个集合中的元素:
示例实现:
// 并集:将other中的元素添加到当前集合,跳过重复元素 public void union(Set other) { for (Zodiac z : other.s) { if (!this.s.contains(z)) { this.s.add(z); } } } // 交集:保留当前集合和other共有的元素 public void intersection(Set other) { Iterator<Zodiac> iter = this.s.iterator(); while (iter.hasNext()) { Zodiac z = iter.next(); if (!other.s.contains(z)) { iter.remove(); } } }
4. 相等性判断需考虑集合的无序性
集合是无序的,但ArrayList是有序的,所以你的equality方法不能只依赖ArrayList的equals(它会检查顺序)。正确的相等性判断应该:
- 先检查两个集合的大小是否一致
- 再检查每个元素都存在于另一个集合中
示例实现:
public boolean equality(Set other) { if (this.s.size() != other.s.size()) { return false; } // 检查当前集合的每个元素都在other中 for (Zodiac z : this.s) { if (!other.s.contains(z)) { return false; } } return true; }
注意:Zodiac类必须正确实现equals()和hashCode()方法,否则contains()无法正确判断元素是否相等。
最后修复后的distributiveExample方法
调整后的完整方法应该是这样的:
private static void distributiveExample() { Set setA = new Set(getASet()); Set setB = new Set(getASet()); Set setC = new Set(getASet()); System.out.printf("We wish to prove: A U (B I C) = (A U B) I (A U C).\n"); System.out.printf("\n"); System.out.printf("Given sets\n"); System.out.printf("\t A = {%s}%n", setA); System.out.printf("\t B = {%s}%n", setB); System.out.printf("\t C = {%s}%n", setC); System.out.printf("\n"); // 计算LHS: A ∪ (B ∩ C) Set lhs = new Set(setA); Set tempBC = new Set(setB); tempBC.intersection(setC); lhs.union(tempBC); System.out.printf("LHS analysis\n"); System.out.printf("\t LHS = {%s}%n", lhs); // 计算RHS: (A ∪ B) ∩ (A ∪ C) Set tempAB = new Set(setA); tempAB.union(setB); Set tempAC = new Set(setA); tempAC.union(setC); Set rhs = new Set(tempAB); rhs.intersection(tempAC); System.out.printf("RHS analysis\n"); System.out.printf("\t RHS = {%s}%n", rhs); System.out.printf("\n"); System.out.printf("Conclusion\n"); System.out.printf("\t LHS = RHS is %b%n", lhs.equality(rhs)); System.out.printf("-----------------------------------------\n"); System.out.printf("\n"); }
按照这些步骤修复后,你的分配律验证应该就能返回正确的true了。
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

