2016-10-19 8 views
1

並列ストリームを使用してJava 8に関して以下のコードを変更する可能性がある場合は教えてください。ストリームを使用したHashMap操作Java 8

"outer for loop"を並列に実行するオプションを探していて、最後にstationMapのすべての値が一緒に収集されますか?

Map<Integer, Set<Integer>> stationMap = new HashMap<>(); 
Map<Integer, Set<Integer>> routes = function(); 
for (Map.Entry<Integer, Set<Integer>> entry : routes.entrySet()) 
{ 
    Set<Integer> stations = entry.getValue(); 

     for (Integer station : stations) { 
     Set<Integer> temporaryStations = new HashSet<>(stations); 
     Set<Integer> stationSet = stationMap.get(station); 
     if (stationSet == null) { 
      stationSet = new HashSet<>(); 
      temporaryStations.remove(station); 
      stationSet.addAll(temporaryStations); 
      stationMap.put(station, stationSet); 
     } else { 
      temporaryStations.remove(station); 
      stationSet.addAll(temporaryStations); 
     } 
     } 
    } 

はもっと短いバージョン:

routes.forEach((k, stations) -> { 
     stations.forEach((station) -> { 
     Set<Integer> stationSet = stationMap.get(station); 
     if (stationSet == null) { 
      stationSet = new HashSet<>(); 
      stationSet.addAll(stations); 
      stationMap.put(station, stationSet); 
     } else { 
      stationSet.addAll(stations); 
     } 
     }); 
    }); 
+0

まず、コードを確認して、何をしているか教えてください。私はこれを単純化できると思う。そこに何か間違っているようです。 > { \t \t \t \t最終セット駅= routes.get(キー - 答えは 'routes.keySet() \t \t \t .parallelStream() \t \t \t .forEach(キー、このようなものを使用することになります); \t \t \t \t局 \t \t \t \t \t .parallelStream()\t \t \t \t \t \t \t \t \t \t \t \t .forEach(V - > stationMap.put(V、ステーション));; \t \t \t}); ' –

+0

ありがとうございました。 stationMap.put(v、station)には小さな問題があります。実際にステーションセットをstationMap( "stationSet.addAll(temporaryStations);")に置くと、以前のステーションを追加しようとしています。問題は今現在のセットを置き換えることです – Dev

+0

私は以前のステーションを取得してそれを追加しようとしましたが、同時に投げられる例外はありません:( – Dev

答えて

2

エントリーセットを反復処理する必要がないとしてあなただけの値を処理し、そこにされている場合でも、長い前のJava 8バージョンは、簡素化することができます2つの条件分岐内のコードの重複の必要はありません:

0:

Map<Integer, Set<Integer>> routes = function(); 
Map<Integer, Set<Integer>> stationMap = new HashMap<>(); 
for(Set<Integer> stations: routes.values()) { 
    for(Integer station: stations) { 
     Set<Integer> temporaryStations = new HashSet<>(stations); 
     temporaryStations.remove(station); 
     Set<Integer> stationSet = stationMap.get(station); 
     if (stationSet == null) { 
      stationMap.put(station, temporaryStations); 
     } else { 
      stationSet.addAll(temporaryStations); 
     } 
    } 
} 

のJava 8つの機能を使用して、あなたが改善されたバリアントを得ることができます

routes.values().forEach(stations -> 
    stations.forEach(station -> { 
     Set<Integer> temporaryStations = new HashSet<>(stations); 
     temporaryStations.remove(station); 
     Set<Integer> old = stationMap.putIfAbsent(station, temporaryStations); 
     if(old!=null) old.addAll(stations); 
    }) 
); 

最初にすべての値をマージし、1つのステップで、その後キーを削除する方が簡単かもしれませんが:

Map<Integer, Set<Integer>> stationMap=routes.values().parallelStream() 
    .flatMap(stations -> stations.stream().map(station -> { 
     Set<Integer> temporaryStations = new HashSet<>(stations); 
     temporaryStations.remove(station); 
     return new AbstractMap.SimpleImmutableEntry<>(station, temporaryStations); 
    }) 
).collect(Collectors.toMap(
    Map.Entry::getKey, Map.Entry::getValue, (a,b) -> {a.addAll(b); return a; })); 

routes.values().forEach(stations -> 
    stations.forEach(station -> 
     stationMap.computeIfAbsent(station, key -> new HashSet<>()).addAll(stations) 
    ) 
); 
stationMap.forEach((k,set) -> set.remove(k)); 

同等の(並列)ストリーム操作を策定することが可能ですこれは、後処理ステップで設定された値からキーを削除するとさらに簡単になります。

Map<Integer, Set<Integer>> stationMap=routes.values().parallelStream() 
    .flatMap(stations -> stations.stream().map(station -> 
     new AbstractMap.SimpleImmutableEntry<>(station, new HashSet<>(stations)) 
    ) 
).collect(Collectors.toMap(
    Map.Entry::getKey, Map.Entry::getValue, (a,b) -> {a.addAll(b); return a; })); 
stationMap.entrySet().parallelStream().forEach(e -> e.getValue().remove(e.getKey())); 

またはあなたの代わりにflatMapのカスタムコレクタを使用します。

Map<Integer, Set<Integer>> stationMap=routes.values().parallelStream() 
    .collect(HashMap::new, 
      (map,stations) -> stations.forEach(station -> 
       map.computeIfAbsent(station, key -> new HashSet<>()).addAll(stations) 
      ), 
      (m1,m2) -> m2.forEach((k,v)->m1.merge(k, v, (a,b)->{a.addAll(b); return a;}))); 
stationMap.entrySet().parallelStream().forEach(e -> e.getValue().remove(e.getKey())); 

、それは一時的なMap.Entryインスタンスを必要としないので、これは、より効率的かもしれません。

+0

ありがとうございます!!!!それは素晴らしいです :) – Dev

関連する問題