回答
大多數時候一組應該只包含immutables。
從the JavaDoc of the Set interface:
注意:如果使用可變對象作爲一組元素大,一定要小心。沒有指定集合的行爲如果對象的值以影響等於比較的方式更改,而對象是集合中的元素,則該對象的值會發生更改。這種禁令的一個特例是,一個集合不允許自己作爲一個元素。
強調我的。
如果您能夠在不影響equals()
的情況下修改元素,我會強烈重新考慮您的等值實現是否正確。
如果程序員編寫調用它的代碼並不會讓任何程序員驚訝,那麼'equals()'的實現就是_correct_。 (這並不意外,任何程序員都會在Set中使用你的類的成員。)如果你是唯一一個會使用你的類編寫代碼的人,那麼你的意見是唯一重要的。另一方面,如果您打算讓您的代碼被其他人重新使用,那麼您可能想要更加認真地考慮其他人期望「equals()」的含義。 –
我不同意。我相信任何'equals'的實現都應該比較每個字段。這是將被普遍理解的* only *實現。如果你想比較一個對象字段的子集,你應該添加另一個明智的命名方法:'isSamePlaceAs()','isSameSizeAs()'等。 – Michael
由於您可以通過修改裏面的可變元素來打破Set
,所以不可變的肯定是首選。
一個問題,舉例來說,就是如果你添加一個A a
一組,然後在改變其哈希碼,有一個機會,set.contains(a)
將返回錯誤的方式發生變異a
。
簡單的例子:
public static void main(String[] args) {
Set<A> set = new HashSet<>();
A a = new A(1);
set.add(a);
System.out.println(set.contains(a)); //true
a.i = 2;
System.out.println(set.contains(a)); //false
}
static class A {
int i;
public A(int i) { this.i = i; }
@Override public int hashCode() { return i; }
}
一個假設你的例子假定一個相應的'equals'實現,即使你沒有顯示它。 –
@LewBloch這個例子不需要工作,但是一般情況下你也可以重寫'equals'。 – assylias
如果'equals'方法返回錯誤的答案,那麼'Set'如何找到該項目?是的,這個例子是必需的。請記住,哈希集合既使用'hashCode'也使用equals。如果它們不一致,代碼就會中斷。實際上,你聲稱破碎的代碼是可以接受的。 –
它最有可能聞起來,因爲如果一個字段被修改,也被用來計算hashCode,Set
打破。因此可以打破Set
。
相反,修改List
中的元素將永遠不會破壞該列表。
簡單的例子(截斷並從assylias擴展回答)
public class Main {
public static void main(String[] args) {
Set<A> set = new HashSet<>();
List<A> list = new ArrayList<>();
A a = new A(1);
set.add(a);
list.add(a);
System.out.println(set.contains(a)); // true
System.out.println(list.contains(a)); // true
a.i = 2;
System.out.println(set.contains(a)); // false
System.out.println(list.contains(a)); // true
}
static class A {
int i;
public A(int i) {
this.i = i;
}
@Override
public int hashCode() {
return i;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof A)) {
return false;
}
A other = (A) obj;
if (i != other.i) {
return false;
}
return true;
}
}
}
假設你的例子假定你有相應的'equals'實現,即使你不要顯示 –
謝謝Lew,固定。 – kerner1000
建議成語:'return i == other.i'。在'if'中使用'boolean'來確定'boolean'有點多餘。 –
- 1. DOM元素可以包含一個包含空格的ID嗎?
- 2. 我可以選擇一個不包含其他元素的元素嗎?
- 3. 變體數組可以包含0個元素嗎?
- 4. MongoDB - 指定集合可能只包含一個文檔
- 5. 斷言集合「至少包含一個非空元素」
- 6. 爲什麼我的集合不包含多個元素? - python 2.7
- 7. Vue js錯誤:組件模板應該只包含一個根元素
- 8. LINQ:查詢集合是否包含另一個集合中的任何元素
- 9. MYSQL:外鍵可以包含一個集合嗎?
- 10. 類應該包含它自己的集合嗎?
- 11. AggregateRoot應該包含其他AggregateRoot的集合嗎?
- 12. 包含wxCheckBox元素的wxTreeCtrl。可能嗎?
- 13. XSLT:XTSE0010:一個fo:block元素不能包含一個xsl:param元素
- 14. HMENU只包含子元素
- 15. 應該JSON Api屬性元素包含嵌套對象嗎?
- 16. 什麼算法來找到包含至少一個元素的最小集合(每個集合包含至少一個元素)
- 17. 一個集合可以有列表作爲其元素嗎?
- 18. Android:創建一個包含可變元素的片段
- 19. 包含應該改變狀態的圖標的按鈕元素
- 20. IOrderedEnumerable <T>是一個固有的不可變集合嗎?我應該/可以屈服嗎?
- 21. 有什麼辦法可以選擇一個包含任何其他集合元素的集合?
- 22. api.raml應該包含整個API嗎?
- 23. hibernate ehcache只發現一個集合中的一個元素
- 24. 包含元素和其他集合用於構造C++的集合的集合
- 25. java.lang.IndexOutOfBoundsException:集合不包含索引4處的元素
- 26. HQL:是另一個集合中的一個集合的元素嗎?
- 27. 如何創建包含2個元素集合的實體?
- 28. 元素的發現數包含兩個集合
- 29. XML元素可以同時包含文本和子元素嗎?
- 30. jq:只選擇一個包含元素A但不包含元素B的數組
它不只是聞。它打破了。 –
取決於哪些字段用於計算hashCode/equals以及哪些字段被修改。 – kerner1000