2016-05-12 64 views
0

我想转换(使用Java 8个流)一Map<Long, List<MyClass>>Map<Long, Set<Long>>其中Set<Long>代表List的每个MyClassidJava的8个流地图<龙,列表<MyClass>>地图<龙,集<Long>>

我曾尝试:

myFirstMap.entrySet().stream() 
     .map(e -> e.getValue().stream() 
      .map(MyClass::getId) 
      .collect(Collectors.toSet())) 

但我不能看到如何得到的结果。

+2

你的编辑无效的答案是已经在这里待了一年。请不要这样做。 – shmosel

回答

4

你映射Map.EntrySet<Long>情况下,这意味着失去跟踪的原始地图的按键,这使得它不可能将其收集到具有相同密钥的新地图的实例。

第一个选项是向Map.Entry<Long, List<MyClass>>实例映射到Map.Entry<Long, Set<Long>>实例,然后收集的条目到一个新的图:

Map<Long, Set<Long>> result= 
    myFirstMap.entrySet().stream() 
     .map(e -> new AbstractMap.SimpleImmutableEntry<>(e.getKey(), 
       e.getValue().stream().map(MyClass::getId).collect(Collectors.toSet()))) 
     .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); 

另一种方法是熔化mapcollect步骤为一体,做变换就在提供给toMap收集值函数:

Map<Long, Set<Long>> result= 
    myFirstMap.entrySet().stream().collect(Collectors.toMap(
     Map.Entry::getKey, 
     e -> e.getValue().stream().map(MyClass::getId).collect(Collectors.toSet()))); 

这样,就避免了创建新Map.Entry实例,并得到但是,更简洁的代码非常灵活,因为您无法链接其他流操作。

0

另一种解决方案,而无需外部Stream的开销是用Map.forEach()这样的:

Map<Long,Set<Long>> result = new HashMap<>(); 
myFirstMap.forEach((k,v) -> 
    result.put(k, v.stream() 
     .map(MyClass::getId) 
     .collect(Collectors.toSet()))); 

这仅仅是一个方便的方法来做到这一点:

Map<Long,Set<Long>> result = new HashMap<>(); 
for (Map.Entry<Long, List<MyClass>> entry : myFirstMap.entrySet()) { 
    result.put(entry.getKey(), entry.getValue().stream() 
     .map(MyClass::getId) 
     .collect(Collectors.toSet())); 
} 
相关问题