【问题标题】:Using java streams, merge two maps having same keys but different values to a Tuple?使用java流,将两个具有相同键但不同值的映射合并到一个元组?
【发布时间】:2019-01-29 09:29:21
【问题描述】:

我有两个具有以下数据类型的地图,

Map<Pair<Long,String>, List<String>>  stringValues;
Map<Pair<Long,String>, List<Boolean>>  booleanValues ;

我想将上面的映射合并到下面的数据结构中

Map<Pair<Long,String>, Pair<List<String>,List<Boolean>>>  stringBoolValues;

我的输入有两个具有相同键但值不同的映射。我想将它们组合成一对。我可以使用 java 流来实现吗?

【问题讨论】:

  • 问题:你的 Pair 类有没有 set 方法?
  • 问题:当一个键出现在一个映射中但不是两个时该怎么办?

标签: java java-8 stream java-stream


【解决方案1】:

前提条件:你已经为Pair&lt;Long, String&gt;正确覆盖了equals()/hashCode()

Map<Pair<Long,String>, Pair<List<String>,List<Boolean>>>  stringBoolValues
   = Stream.of(stringValues.keySet(),booleanValues.keySet())
      .flatMap(Set::stream)
      .map(k -> new SimpleEntry<>(k, Pair.of(stringValues.get(k), booleanValues.get(k))) 
      .collect(toMap(Entry::getKey, Entry::getValue));

Pair.of 在哪里:

public static Pair<List<String>,List<Boolean>> of(List<String> strs, List<Boolean> bls) {
    List<String> left = Optional.ofNullable(strs).orElseGet(ArrayList::new);
    List<Boolean> right = Optional.ofNullable(bls).orElseGet(ArrayList::new);
    return new Pair<>(left, right);
}

您甚至可以使用 Map.computeIfAbsent 来避免显式检查 null 的需要。

【讨论】:

  • 前置条件在这里没有任何意义。
  • 您愿意详细说明吗???如果不正确覆盖等于,则无法合并值
  • Pair, Long, String 这些是组成映射中键的类。为什么你认为它需要覆盖默认的 hashCode 和 equals 行为。在这些类中定义的默认行为已经足够好了。
  • @HimanshuBhardwaj 在不知道Pair 类的默认行为的情况下,您如何确定“在这些类中定义的默认行为已经足够好”?问题中没有任何提示,Pair 类来自哪里以及它是如何实现的。
  • @Holger:commons.apache.org/proper/commons-lang/apidocs/org/apache/… Apache 的 Pair 数据结构是这里讨论的内容。
【解决方案2】:

其他简单的方法是这样的:

stringValues.forEach((key, value) -> {
        Pair<List<String>, List<Boolean>> pair = new Pair<>(value, booleanValues.get(key));
        stringBoolValues.put(key, pair);
});

stringBoolValues = stringValues
            .entrySet()
            .stream()
            .collect(Collectors.toMap(Map.Entry::getKey, 
  entry -> new Pair<>(entry.getValue(), booleanValues.get(entry.getKey()))));

试试这样:

Set<Pair<Long,String>> keys = new HashSet<>(stringValues.keySet());
keys.addAll(booleanValues.keySet());

keys.stream().collect(Collectors.toMap(key -> key, 
           key -> new Pair<>(stringValues.get(key), booleanValues.get(key))));

【讨论】:

  • 如果少数键只存在于 booleanValues 而不是 stringValues 怎么办?我在 stringBoolValues 中也需要它们
【解决方案3】:

只需使用Collectors.toMap 中的valueMapper 即可轻松合并 两个不同映射中的值:

Map<Pair<Long, String>, Pair<List<String>, List<Boolean>>> stringBoolValues = stringValues.entrySet().stream()
            .collect(Collectors.toMap(Map.Entry::getKey, entry -> new Pair(entry.getValue(), booleanValues.get(entry.getKey()))));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    相关资源
    最近更新 更多