将集合转换为Map <string,collection <string>&gt;使用java 8流

时间:2016-08-15 00:52:26

标签: java lambda java-stream

我希望使用java流将Collection<Placement>转换为Map<String, Collection<String>>,其中Placement类如下所示

public class Placement {

   private String id;

   /* Links two placements, may be same for atleast 2 placements. */
   private String futureLinkId;
}

地图的关键是未来的链接ID,值是放置ID。例如,如果有2个展示位置 p1 { id=1, futureLinkId=f1 }, p2 { id=2, futureLinkId=f1 },输出应为Map { f1 - { id1, id2 } }

3 个答案:

答案 0 :(得分:3)

这实际上非常简单,尽管其他人提供了令人费解的解决方案:

Map<String, List<String>> map = placements.stream()
        .collect(groupingBy(Placement::getFutureLinkId, mapping(Placement::getId, toList())));

答案 1 :(得分:0)

您只需按futureLinkId分组,然后将值映射到id。写它的一种方法:

Map<String, List<String>> result = Stream.of(new Placement("id1", "f1"), new Placement("id2", "f1"))
        .collect(Collectors.groupingBy(Placement::getFutureLinkId))
        .entrySet()
        .stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().stream().map(Placement::getId).collect(Collectors.toList())));
System.out.println(result);

输出:

{f1=[id1, id2]}

为了让它看起来更漂亮,我建议写两个帮手:

public static <K, V, N> Map<K, N> mapValues(Map<K, V> map, Function<V, N> mapper) {
    return map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, mapper.compose(Map.Entry::getValue)));
}

public static <T, R> List<R> map(List<T> list, Function<T, R> mapper) {
    return list.stream().map(mapper).collect(toList());
}

然后

Map<String, List<String>> result = Stream.of(new Placement("id1", "f1"), new Placement("id2", "f1")).collect(
    collectingAndThen(groupingBy(Placement::getFutureLinkId),
                      res -> mapValues(res, list -> map(list, Placement::getId))));

System.out.println(result);

答案 2 :(得分:0)

使用three-argument toMap是实现所需目标的一种方式。 (groupingBy似乎是另一个,但我并不熟悉该方法。)

对于toMap,您需要一个将Placement映射到键的函数;将Placement映射到某个值的函数,在这种情况下,该值必须是 set 值;最后一个函数将两个值合并在一起,如果它们具有相同的键。像

这样的东西
Map<String,HashSet<String>> result =
    placements.stream()
        .collect(Collectors.toMap
             (placement -> placement.futureLinkId,
              placement -> new HashSet(Collections.singleton(placement.id)),
              (s1, s2) -> { HashSet<String> result = new HashSet<>(s1);
                            result.add(s2);
                            return result; }));

注意:我还没有对此进行过测试。如果流是顺序流,则可以在不复制s1的情况下工作。

相关问题