我有一個圖如下:返回不可修改的映射
Map<String,Map<String,Object>>
給定一個鍵,我將返回地圖。
推薦使返回的Map不可變的方法是什麼?
這基本上意味着:
地圖是不變的(無修改/刪除/添加)
底層對象是不可變的(無編輯)
我們沒有其他選擇,使對象不可改變。
我有一個圖如下:返回不可修改的映射
Map<String,Map<String,Object>>
給定一個鍵,我將返回地圖。
推薦使返回的Map不可變的方法是什麼?
這基本上意味着:
地圖是不變的(無修改/刪除/添加)
底層對象是不可變的(無編輯)
我們沒有其他選擇,使對象不可改變。
你需要做的是做一個返回地圖的深層副本。
可以讓每個地圖不可修改,然後使整個地圖不可修改。
public Map<String,Map<String,Object>> makeUnModifiable(Map<String,Map<String,Object>> a){
for(Entry<String, Map<String, Object>> e:a.entrySet()){
e.setValue(Collections.unmodifiableMap(e.getValue()));
}
return Collections.unmodifiableMap(a);
}
真正的問題是,您仍然提供對地圖中值的訪問。您可以創建這些對象的副本,但這並不能解決問題。可以使對象類不可變或爲它們創建一個禁用setter方法的Wrapper類。
這不會使問題中的對象本身不可修改。 – RealSkeptic
@RealSkeptic是真的。這隻能以非常有限的方式完成,每個方法都需要知道對象類。 – f1sh
通過擴展AbstractMap
,您可以製作一張不可修改的地圖,其地圖值也不可修改。
要實現不可修改的映射,程序員僅需要擴展此類並提供
entrySet
方法,它返回地圖的映射的一組視圖的實現。通常,返回的集合將依次在AbstractSet
之上實現。該集不應該支持add
或remove
方法,其迭代器不應該支持remove
方法。
package mcve;
import java.util.*;
public final class UnmodifiableMapOfMaps<K, L, V> extends AbstractMap<K, Map<L, V>> {
// Optionally Map<? extends K, ? extends Map<? extends L, ? extends V>>
// but it would make the code a lot more difficult to read.
private final Map<K, Map<L, V>> map;
public UnmodifiableMapOfMaps(Map<K, Map<L, V>> map) {
this.map = Objects.requireNonNull(map);
}
// Additionally override size(), get(), etc., entirely optionally.
// Doing so would merely be an optimization since AbstractMap
// implements those methods via the entrySet() iterator.
@Override
public Set<Entry<K, Map<L, V>>> entrySet() {
return new AbstractSet<Entry<K, Map<L, V>>>() {
@Override
public int size() {
return map.size();
}
@Override
public Iterator<Entry<K, Map<L, V>>> iterator() {
return new Iterator<Entry<K, Map<L, V>>>() {
private final Iterator<Entry<K, Map<L, V>>> it = map.entrySet().iterator();
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public Entry<K, Map<L, V>> next() {
// Return the Entry as an immutable Entry with an
// unmodifiableMap as the value.
Entry<K, Map<L, V>> entry = it.next();
K key = entry.getKey();
Map<L, V> val = Collections.unmodifiableMap(entry.getValue());
return new SimpleImmutableEntry<>(key, val);
}
};
}
};
}
}
抽象的集合是真正偉大的階級熟悉,因爲他們做了很多的問題,像這個相當平凡解不從頭開始編寫一個新的容器。
除了編寫不可變對象外,沒有辦法在Java中創建不可變對象。 Java沒有像例如const
在C++中。要做到這一點,而無需實際實例化一個新的對象
一種方法是編寫接口如下,然後返回ImmutableFoo
你不想暴露二傳手任何時間:
interface ImmutableFoo {
int getValue();
}
interface MutableFoo extends ImmutableFoo {
void setValue(int value);
}
class Foo implements MutableFoo {
private int value;
public Foo(int value) { this.value = value; }
@Override public int getValue() { return value; }
@Override public void setValue(int value) { this.value = value; }
}
否則,如果Foo
是一個你無法改變的課程,你必須寫下如下內容:
class FooAccessor {
private final Foo foo;
public FooAccessor(Foo foo) { this.foo = Objects.requireNonNull(foo); }
public int getValue() { return foo.getValue(); }
}
其中任何一個都可以使用eg結合不可修改的AbstractMap
示例。
[返回一個不可修改的映射]可能的副本(https://stackoverflow.com/questions/7066618/returning-an-unmodifiable-map) –
沒有辦法指定一個對象是不可變的,除了寫一個不可變的目的。正如我理解你的問題,你實際上並沒有真正想讓地圖不可變,而是詢問如何使地圖中的對象不可變。那是對的嗎?換句話說,你基本上需要像C++'const'這樣的東西,但在Java中不存在。你必須編寫一個包裝對象的代理,並且不提供setter或throws異常。使用界面有幫助。 – Radiodef
你實際上需要不可變的'Object' _forfor?不知道這一點,很難提供任何有用的建議。 – Rook