2017-05-24 14 views
0

を返す:変更不可能なマップ

Map<String,Map<String,Object>> 

が鍵を考えると、私は地図を返されます。
返されるマップを不変にするための推奨される方法は何ですか? (無編集/削除/追加)
基礎となるオブジェクトは、我々は、オブジェクトは不変にするnoオプションを持っていない

不変(無編集)されない
地図は不変である:
これは、本質的にことを意味します。

+0

[変更可能なマップを返す](https://stackoverflow.com/questions/7066618/returning-an-unmodifiable-map)の可能な複製 –

+1

オブジェクトが不変であることを指定する方法はありません。オブジェクト。私はあなたの質問を理解しているので、マップを不変にすることを実際に求めているわけではありません。マップ内のオブジェクト*を不変にすることを求めています。あれは正しいですか?別の言い方をすると、基本的にはC++の 'const'のようなものが欲しいですが、それはJavaでは存在しません。オブジェクトをラップするプロキシを記述する必要があり、セッターや例外をスローしません。インターフェイスを使用すると便利です。 – Radiodef

+1

実際には不変の 'Object' _for_が必要ですか?それを知らずに、有用な助言をするのは難しいです。 – Rook

答えて

1

その後、全体マップが変更不可能にする、各マップは変更不可能にすることができます。

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クラスを作成します。

+0

それは、問題で必要に応じてオブジェクト自体を変更不可能にするものではありません。 – RealSkeptic

+0

@RealSkepticそれは本当です。これは、オブジェクトクラスを知る必要がある非常に限られた数の方法でのみ行うことができます。 – f1sh

0

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には、例えばC++のconst

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がある場合:実際に新しいオブジェクトをインスタンス化せずにこれを行うには

一つの方法は、次のようにImmutableFooあなたがセッターを公開したくない任意の時刻を返し、その後、インターフェースを書くことですあなたが変更できないクラスであれば、次のようなものを書く必要があります:

class FooAccessor { 
    private final Foo foo; 
    public FooAccessor(Foo foo) { this.foo = Objects.requireNonNull(foo); } 
    public int getValue()  { return foo.getValue(); } 
} 

変更不可能なAbstractMapの例と組み合わせて使用​​します。

関連する問題