2017-05-08 4 views
1

特有のキー以外のマップのリストがあり、ストリーミングAPIで各マップ値を変更したいのですが。結果は新しいリストでなければならず、元のものは変更されないままでなければなりません。ストリーミングAPIを使用したマップリストの値を換算する

例データ:

// [ {jpg=firstImage.jpg, png=firstImage.png}, {jpg=secondImage.jpg, png=secondImage.png} ] 
Map<String, String> map1 = new HashMap<>(); 
map1.put("jpg", "firstImage.jpg"); 
map1.put("png", "firstImage.png"); 
Map<String, String> map2 = new HashMap<>(); 
map2.put("jpg", "secondImage.jpg"); 
map2.put("png", "secondImage.png"); 
List<Map<String, String>> list = new ArrayList<>(); 
list.add(map1); 
list.add(map2); 

のは、私が大文字にファイル名を変換したいと仮定しましょう。私は次の操作を行うことができ、独特の値を持つ:

Map<String, String> copy = list.stream() 
       .flatMap(e -> e.entrySet().stream()) 
       .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().toUpperCase())); 

しかしキーが独特でないときflatMapは動作しません、それは私のList<Map<String, String>>構造を破壊するであろう。私は構造が悪いことを知っていますが、私はそれを変更することはできません。

期待される成果は:

// [ {jpg=FIRSTIMAGE.JPG, png=FIRSTIMAGE.PNG}, {jpg=SECONDIMAGE.JPG, png=SECONDIMAGE.PNG} ] 

私は、ストリーミングAPIでこれを達成し、可能な場合は、ネストされたループを避けるためにしたいと思います。

答えて

3

flatMapを使用することはできません。この方法では、1つのストリーム内のすべてのエントリを連結して戻す可能性が失われるためです。あなたは、例えば次のように、あなたのListから個々の要素を変換する必要が

は:

List<Map<String, String>> result = list.stream() 
      .map(map -> map.entrySet().stream() 
          .collect(Collectors.toMap(
            Map.Entry::getKey, 
            e -> e.getValue().toUpperCase()))) 
      .collect(Collectors.toList()); 

    System.out.println(result); 
    // [{jpg=FIRSTIMAGE.JPG, png=FIRSTIMAGE.PNG}, {jpg=SECONDIMAGE.JPG, png=SECONDIMAGE.PNG}] 
+0

ネストされたストリームはありませんでした。ありがとう! – moeTi

1

ここで私はあなたのリスト内の既存のマップを変更していますオプション

list.forEach(map -> map.replaceAll((t, f) -> f.toUpperCase())); 

です。ストリームを使用していません。

編集:VGRのおかげで大幅に簡素化されました。

編集:元の構造をそのままにしておく必要があるため、Eugene’s solutionは問題ありません。コピーにreplaceAll()を適用することもできます。一つの例:

List<Map<String, String>> result = new ArrayList<>(list); 
    list.replaceAll(m -> { 
       Map<String, String> newMap = new HashMap<>(m); 
       newMap.replaceAll((t, f) -> f.toUpperCase()); 
       return newMap; 
      }); 

か、まだ別のアプローチ

、ストリームで、この1:

List<Map<String, String>> result = list.stream() 
      .map(m -> { 
       Map<String, String> newMap = new HashMap<>(m); 
       newMap.replaceAll((t, f) -> f.toUpperCase()); 
       return newMap; 
      }) 
      .collect(Collectors.toList()); 

、好む私は、それは主に好みの問題だと思います。

+0

提案のおかげで、それは入れ子になったストリームよりもきれいです。しかし、元の構造は変わらないと付け加えることを忘れてしまった。 – moeTi

+0

実際にはネストされたストリームもあります。あなたの要件は驚くべきではないはずです。私は[Eugene's solution](http://stackoverflow.com/a/43849203/5772882)よりも優れたものを提案することはできません。 –

+1

list.stream()。forEachは単に 'list.forEach'として書くことができます。 (実際は、全体の文を 'list.forEach(map - > map.replaceAll((t、f) - > f.toUpperCase()))'に短縮することができます。 – VGR

関連する問題