2017-08-04 27 views
3

ConcurrentHashMapを初期化する「CLEAN & Simple」メソッドを探しています。私は、この持っているのJava 8でJava 8 ConcurrentHashMapの初期化

: - 所望の最終結果を提供

private static final Map<String, String> myStreamedMap = Stream.of(
     new AbstractMap.SimpleImmutableEntry<>("Key1", "Value1"), 
     new AbstractMap.SimpleImmutableEntry<>("Key2", "Value2"), 
     new AbstractMap.SimpleImmutableEntry<>("Key3", "Value3"), 
     new AbstractMap.SimpleImmutableEntry<>("Key4", "Value4")). 
     collect(Collectors.toMap((entry) -> entry.getKey(), (entry) -> entry.getValue())); 

は、しかし、私は

"new AbstractMap.SimpleImmutableEntry<>"

が起こっていただきました、それは難しいご覧になり感じます。

これを「非表示」して1行にすることはできますか?

UPDATE

は、Java 9がリリースされるまで、そこに内蔵されたマップの初期化メソッドがない便利であるので、私は第三を見てお勧めします。この(明らかな)ソリューション

private static final Map<String, String> myStreamedMapWith = Stream.of(
     with("Key1", "Value1"), 
     with("Key2", "Value2"), 
     with("Key3", "Value3"), 
     with("Key4", "Value4")). 
     collect(Collectors.toMap((entry) -> entry.getKey(), (entry) -> entry.getValue())); 

private static AbstractMap.SimpleImmutableEntry<String, String> with(final String key, final String value) { 
    return new AbstractMap.SimpleImmutableEntry<>(key, value); 
} 
+1

は、あなたが期待したことを説明する独自の方法を抽出します。例えば: 'mapOf(" foo "、" bar ")、...、with(" key "、" value "));' –

+0

@AndrewTobilko私は "自己文書化"ソリューションを探しています。 Builderパターンのように。 De Duplicationを追加することができました。一つの制約は、私が標準のJavaソリューションを好むことです。 – Hector

+0

'static {}'ブロックを使用していますか?それは単線ではなく文字数ではるかに短いです – the8472

答えて

5

を思い付い(Googleのグアバのような)パーティ製ライブラリは:

new ConcurrentHashMap<>(com.google.common.collect.ImmutableMap.of("Key1", "Value1")); 

とにかく、ここでの主な問題は、あなたがHashMapのインスタンスを作成しているということです。 Collectors.toMapソースから

return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); 

あなたが任意の外部ライブラリを使用したくない場合は、行くには良い方法はthe Builder patternを使用しています。ここでは簡単な例です:

class MapBuilder<K, V> { 

    private List<Map.Entry<K, V>> entries = new ArrayList<>(); 

    public MapBuilder<K, V> with(K key, V value) { 
     entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value)); 

     return this; 
    } 

    public Map<K, V> build(Supplier<Map<K, V>> mapSupplier) { 
     return entries.stream().collect(Collectors.toMap(
       Map.Entry::getKey, 
       Map.Entry::getValue, 
       (k1, k2) -> k1, 
       mapSupplier 
       ) 
     ); 
    } 

} 

とそのデモンストレーション:

new MapBuilder().with("Key1", "Value1") 
       .with("Key2", "Value2") 
       .build(ConcurrentHashMap::new); 

実装の完全独立しているように(AbstractMap.SimpleImmutableEntry)、私はようBiFunction<KEY, VALUE, Map.Entry<KEY, VALUE>>エントリ初期化子を取るコンストラクタを導入することをお勧め引数:

class MapBuilder<K, V> { 

    private List<Map.Entry<K, V>> entries; 
    private BiFunction<K, V, Map.Entry<K, V>> function; 

    public MapBuilder() { 
     entries = new ArrayList<>(); 
    } 

    public MapBuilder(BiFunction<K, V, Map.Entry<K, V>> function) { 
     this(); 
     this.function = function; 
    } 

    public MapBuilder<K, V> with(K key, V value) { 
     entries.add(function.apply(key, value)); 

     return this; 
    } 

    public Map<K, V> build(Supplier<Map<K, V>> mapSupplier) { ... } 

} 

コールは次のように変更されます:

new MapBuilder<>(AbstractMap.SimpleImmutableEntry::new); 

この時点で、エントリとマップの両方にどのインプリメンテーションを選択するかを決めることができます。

+0

素敵な仕事、私はあなたがentries.stream()を意味していたと思います。(toMap to ... entries.stream()。collect(Collectors.toMap ...? – Hector