2016-10-19 125 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

首先您可以查看您的代碼並告訴我們您在做什麼?我認爲這可以簡化。看起來有點不妥。答案是使用這樣的事情,'routes.keySet() \t \t \t .parallelStream() \t \t \t .forEach(鍵 - > { \t \t \t \t決勝盤站= routes.get(關鍵); \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可以簡化爲沒有必要遍歷條目集,當你只處理價值和有無需代碼重複這兩個條件分支中:

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); 
    }) 
); 

,雖然這可能是簡單的,首先合併所有值,並在一個步驟之後刪除鍵:

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 -> { 
     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; })); 

但是在從後處理步驟中設置的值中移除鍵時,這也可能更簡單:

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