我有一個地圖Map<String, SomeType>
其中SomeType
的每個實例都按照名稱添加,如map.put(object.getName(), object)
。最後,map.values()
中沒有重複。如何將Map.values作爲集合而不是集合?
現在,我想要一個Set<SomeType>
從這張地圖沒有複製像new HashSet<>(map.values())
。
這是可能的,只與標準庫優惠嗎?
我有一個地圖Map<String, SomeType>
其中SomeType
的每個實例都按照名稱添加,如map.put(object.getName(), object)
。最後,map.values()
中沒有重複。如何將Map.values作爲集合而不是集合?
現在,我想要一個Set<SomeType>
從這張地圖沒有複製像new HashSet<>(map.values())
。
這是可能的,只與標準庫優惠嗎?
您已經知道如何處理new HashSet<>(map.values())
。您無法直接獲取一組值,因爲這些值可能包含重複項。即使在您的特定地圖中沒有重複值,但在一般地圖中,可能會有重複值。
你可以用Java 8 Streams做些什麼,但是它沒有明確的實例化Set。
Set<SomeType> values = map.values().stream().collect(Collectors.toSet());
沒有Collection
包裝它是不可能的。
僅僅因爲在你的情況下沒有重複,這並不意味着他們不能。
Java Collections API允許您在Map
中輸入重複值,所以合同必須返回Collection
而不是Set
。
這將是一個簡單的事情,創造一個Set
查看任何Collection
的。
public final class SetView<E> extends AbstractSet<E> {
private final Collection<? extends E> collection;
private SetView(Collection<? extends E> collection) {
this.collection = collection;
}
public static <E> SetView<E> of(Collection<? extends E> collection) {
return new SetView<>(collection);
}
@Override
public boolean contains(Object e) {
return collection.contains(e);
}
// rest omitted.
}
有了這個,你可以再寫入Set<E> set = SetView.of(map.values());
並向Map
所有更改會自動在Set
反映。
這種方法的問題是如果不復制Collection
,某些方法將很難實現。例如,你會怎麼寫size()
?
最明智的辦法就是
@Override
public int size() {
return new HashSet<>(collection).size();
}
但這違背了使用一個視圖,而不是僅僅複製擺在首位的要素的目的。如果您知道Collection
永遠不會包含重複的,你可以簡單做
@Override
public int size() {
return collection.size();
}
不過,我會建議對這樣的做法。 A Map
允許包含重複值,並且添加兩個具有相同值的條目的可能性意味着Set
的合同將被打破。
除非你有很不想複製元素的好理由,我只會用new HashSet<>(map.values())
。
它不是一個集合。你將不得不復制一份。或者只是使用收集,知道沒有重複。 – EJP