2016-05-05 18 views
0

私は同じ鍵(仮定)を持つと考えられる2つのMapを持っています。Java 8のマップ値とストリームの結合

は私が対応する要素

上でアクションを実行する必要が

のJava 7のコード:私の目標は

何か

Map<X,Y> m1, m2; 

[initStreamHere](m1, m2).forEachCorrespondingEntry((k, v1, v2)-> doSomething(v1, v2)); 
のような操作のためのラムダを使用することです
Map<X,Y> m1, m2; 

for (Map.Entry<X,Y> kvp: m1.entrySet()) { 
    K key = kvp.getKey(); 
    Y value1 = kvp.getValue(); 
    Y value2 = m2.get(key);  


    doSomething(value1, value2); 
} 

一般に、v1またはの場合は涼しいかもしれませんは対応するキーの有無に応じてヌルであるかどうかを示します。

Javaはそのような優れた機能を提供しますか?または、50行未満でカスタムコードを実装することは可能ですか?

私の目標は、このような何かを、キーを取り、2つのに対応する値

+1

m1' 'オーバーだけ' forEach'、によって提供さ 'm1'キーで' GET'を使用して 'm2'をキャプチャ'forEach'を呼び出して' doSomething'を呼び出します。 –

+0

Uhmmm ... Javaがm2のルックアップを処理して、結果を提供してくれるかどうかを尋ねていただけです。私はすでにコードを古いJava 7の方法で実装しています。 PSではm1にストリームするのが無用でm2に乗る必要があります。私は上司に印象的な例を示しました。 –

+0

2つのマップから 'MultiMap'を作成し、それらの結果をストリームします。または、2つの値を持つ独自の 'Map'を作成し、それをストリームします(' Collection'または 'List'値を扱う必要はありません)。 –

答えて

1

奇妙な質問だけです。プロダクション/仲間のために、はるかに理解できるものを書く方が良いです。

interface EntryConsumer<K, V> { 
    void apply(K key, V v1, V v2); 
} 

public static <K, V> void fancyStreams(Map<K, V> m1, Map<K, V> m2, EntryConsumer<K, V> consumer) { 
    Stream 
     .concat(m1.entrySet().stream(), m2.entrySet().stream()) 
     .filter(e -> e.getValue() != null) // filter out nulls 
     .collect(Collectors.groupingBy(Map.Entry::getKey)) 
     .entrySet() 
     .stream() 
     .filter(e -> e.getValue().size() == 2) // filter out non-matching key-values 
     .forEach(e -> consumer.apply(e.getKey(), e.getValue().get(0).getValue(), e.getValue().get(1).getValue())); 
} 

public static <K, V> void plainOldIteration(Map<K, V> m1, Map<K, V> m2, EntryConsumer<K, V> consumer) { 
    m1.entrySet() 
     .forEach(e -> { 
      if (m2.containsKey(e.getKey())) 
       consumer.apply(e.getKey(), e.getValue(), m2.get(e.getKey())) 
     }); 
} 

// Actual usage 
Map<String, Integer> m1, m2; 
m1 = Maps.of("1", 22, "2", 23); 
m2 = Maps.of("1", 20, "2", 19, "3", 21); 
fancyStreams(m1, m2, (k, v1, v2) -> System.out.println(k + ": " + (v1 + v2))); 
plainOldIteration(m1, m2, (k, v1, v2) -> System.out.println(k + ": " + (v1 + v2))); 

そして、あなたの実際の要求(少し冗長)

public class EntryStream<K, V> { 

    private final Map<K, V> m1; 
    private final Map<K, V> m2; 

    private EntryStream(Map<K, V> m1, Map<K, V> m2) { 
     this.m1 = m1; 
     this.m2 = m2; 
    } 

    public static <K, V> EntryStream<K, V> of(Map<K, V> m1, Map<K, V> m2) { 
     return new EntryStream<>(m1, m2); 
    } 

    public void forEachCorrespondingEntry(EntryConsumer<K, V> consumer) { 
     m1.entrySet() 
      .forEach(e -> { 
       if (m2.containsKey(e.getKey())) consumer.apply(e.getKey(), e.getValue(), m2.get(e.getKey())); 
      }); 
    } 
} 

// Usage 
EntryStream.of(m1, m2).forEachCorrespondingEntry((k, v1, v2) -> System.out.println(k + ": " + (v1 + v2))); 
+0

信じられないほど閉じます。私はlambdaですべてのロジックを実装する必要はありません、私はlambdaで "インターフェイス"が必要です。なぜなら、forEachCorrespondingEntry((k、v1、v2) - > 'を書くことができる限り、それは素晴らしいことです)バッキングの実装でストリームまたは普通の古いループを使用すると、それはちょうど良いでしょう –

+0

なぜEntryStreamはあなたが必要とするものではありませんか?Btw、2つ以上のマップに一般化するのは簡単です – qwwdfsad

+0

いいえ残念ですが、最初のフラグメントのチェーン呼び出しについて話していました –

-1

ラムダ式を使用することですか?

m1.entrySet() 
    .stream() 
    .filter(kvp -> m2.containsKey(kvp.getKey())) 
    .forEach(kvp -> doSomething(kvp.getValue(), m2.get(kvp.getKey()))); 
+0

いいえ、申し訳ありませんが、私は3をすべて取るラムダを持っていました。私は何かにこだわっているわけではないので、好奇心と楽しみのために全体の質問をしています:-) –

0

ここで私はあなたがここにあなたの目的のために

public class MapCombine { 

public static Map<String,Integer> combineMaps(Map<String,Integer>map1,Map<String,Integer>map2){ 
    map2.forEach((key,value)->{ 
     map1.merge(key, map1.get(key), MapCombine::combine); 
    }); 
    return map1; 
} 

public static int combine(Integer a , Integer b) { 
    return a+b; 
} 

public static void main (String ...args) { 
    Map<String,Integer>map1 = new HashMap<>(); 
    Map<String,Integer>map2 = new HashMap<>(); 
    map1.put("Red", 1); 
    map1.put("Blue", 12); 
    map1.put("Black", 11); 
    map2.put("Red", 1); 
    map2.put("Blue", 111);  

    // This will print total for each color 
    System.out.println(combineMaps(map1, map2)); 

} 

}

をマージ機能を使用する方法の良い例を書いた出力{赤= 2、青= 24、ブラック= 11であります}

関連する問題