[英]Why java.util.Set does not contain value getter? Are there alternatives to it?
由於集合條目僅由屬性的子集( hashCode()
+ equals()
)區分,因此有時需要對集合中包含的原始對象進行操作,這對於java.util.Set
是不可能的。 我想出的唯一選擇是: Map<T, T>
- 不是一個非常簡潔的解決方案。
收集框架中還有其他替代方案嗎? 要求是:O(1)獲取時間並且沒有基於hashCode() + equals()
結果的重復。
如果還有一個O(1)操作沒有問題,你可以使用set.remove(Object)
和set.add(Object)
方法對模擬 absenting方法get(Object)
set.add(Object)
。 否則,我會使用你提到的Map<T,T>
或帶底層地圖的簡單包裝類 。
編輯 : Set
不包含get(Object)
是你不需要返回你知道的對象。 如果您的對象包含在set中,您只需要檢查。
不是在java.util.Collections
本身,而是使用Google Guava ,您可以使用Iterables.get
從給定的Iterator
檢索任何元素。
通常我不會提倡外部庫,但考慮到Guava是多么強大和有用,我認為沒有問題。
或者,您可以使用自己的實現迭代該集合。
另外,我在這里發現了一個非常有趣的線程來解釋這種行為。
Set
不能包含兩個對象o1
和o2
,以便o1.equals(o2
)(在此標准中不使用hashCode
)。
HashSet
正在使用散列圖來有效地存儲其對象,因此最終HashMap正是您基於hashCode()+equals()
的操作所需要的。
如果你想重用它,我寫了這樣一個類。 Jayes包含一個類org.eclipse.recommenders.jayes.util.sharing.CanonicalSet
,它允許基於幾乎任何可以在hashCode()
和equals()
實現中編碼的等價關系進行檢索。 我用它來構建數組等價類。 您可以查看CanonicalSet
那些實現,它們位於同一個包中。
哦,但是,它也只是基於Map<Entry<T>,T>
,所以沒有什么神奇的。
基於HashMap的HashSet代碼非常簡單:如果你看一下它在JDK中的實現方式, 實際代碼的行很少(忽略構造函數和序列化代碼)。
在這樣做的方法是使用額外的get()
方法實現自己的HashSet版本
public E get(Object o) {
return map.get(o);
}
您可以使用commons-collections中的 SetUniqueList
它裝飾了一個java.util.List
以確保不會像java.util.Set
那樣存在重復項。
是的,它有點痛苦,無法分享同等對象。 Set API的問題是,缺少特定的addAndGet:
AddOnceSet<String> set = new AddOnceSet<>();
String s = in.readLine();
s = set.addOnce(s); // The new s is equal, and identical to the first added one.
s = set.getOnce(s);
不幸的是,這不適合集合API。 我希望這可能是Java 8+。 在Java 8中,您可以為addOnce
和getOnce
添加一個默認接口。
像你說的那樣實現:
private Map<T, T> sharedThings = new HashMap<>().
public T shareThing(T s) {
String t = sharedThings.get(s);
if (t == null) {
t = s;
sharedStrings.put(t, t);
}
return t;
}
...
public void setT(T t) {
this.t = sharedThing(t);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.