2016-03-23 13 views
8

を使用してハッシュマップの値を文字列で置き換えますforEachの本文には再割り当てできません。は、私はコード以下のような<code>String</code>と<code>HashMap</code>持っているJavaの8ストリーム

StringHashMapに置き換えるソリューションは、Java 8 Stream APIを使用していますか?これは(messageを効果的に最終でなければならない)のみforEach()を用いて作製することができないよう

+2

'forEachの()は'同期されていません。あなたのラムダ式の中から 'message'に副作用を与えることはできないので、あなたのコードはコンパイルされません。可能な場合であっても、マップ内の最後のマップエントリに対する 'test'の最後の置き換えを含む' message'だけが得られます。おそらくあなたが望むものではありません。また、「最後のマップエントリ」は、「HashMap」に対して非決定的であるからです。 – Ralf

+0

ありがとう、私はそれを得た。すでに置き換えられたテストのすべての内容を取得するにはどうすればよいですか? –

答えて

3

、この問題を回避するには、再書き込みされる単一Stringを格納する最終容器(例えばList)を作成することができ:

final List<String> msg = Arrays.asList("helloABC"); 
map.forEach((key, value) -> msg.set(0, msg.get(0).replace(key, value))); 
String test = msg.get(0); 

以前は正規表現で動作していたが、コードで判断すると文字列で置き換える必要があると思われるので、replaceAll()replace()に変更したことに注意してください(混乱しているにもかかわらず、すべての出現を置き換えます)。

あなたは正確にAPIをストリームする場合は、あなたがreduce()操作使用することができます:

String test = map.entrySet() 
       .stream() 
       .reduce("helloABC", 
         (s, e) -> s.replace(e.getKey(), e.getValue()), 
         (s1, s2) -> null); 

をしかし、そのような減少は唯一のコンバイナ機能があるシリアル(平行でない)ストリーム、で正しく機能することは、考慮に入れます呼び出されることはありません(したがって、何でもよい)。

+0

私はすでにそれを試しましたが、それはとても難しいようです。 Mapに多くの要素がある場合はどうすればよいでしょうか? –

+0

@ChheaVanrin '0'は' List'を指し、 'Map'は指しません。 'forEach()'はあなたが持っているものと同じくらいたくさんのマップエントリを処理します。 –

+0

申し訳ありませんが、私はそれをはっきりと見ませんでした。それほど論理的ではないようです。私はちょうど完全にJava 8ストリームで作業したい。とにかくありがとう:) –

3

この種の問題は、Streams APIにはあまり適していません。 Streamsの現在のインカネーションは、主に並列化できるタスクを対象としています。おそらく、このタイプの操作のサポートは将来追加されるでしょう(https://bugs.openjdk.java.net/browse/JDK-8133680参照)。あなたは面白いかもしれません

つのストリームベースのアプローチは機能上ではなく、文字列に削減することです:

Function<String, String> combined = map.entrySet().stream() 
    .reduce(
     Function.identity(), 
     (f, e) -> s -> f.apply(s).replaceAll(e.getKey(), e.getValue()), 
     Function::andThen 
    ); 

String result = combined.apply(test); 
+3

Java-9で 'foldLeft'を見る機会がないようです。残念ながら。 –

+1

@TagirValeev数か月前にcore-libメーリングリストにあなたの努力を見ました。試していただきありがとうございます。 – Misha

関連する問題