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