【问题标题】:How to return the key with the most associated values inside a HashMap如何在 HashMap 中返回具有最相关值的键
【发布时间】:2021-05-16 11:38:59
【问题描述】:

我目前有一个“HashMap”形式的 HashMap,其中包含一个键(一个项目)和一个值(与该项目关联的所有项目的 HashSet)。

我正在尝试在类中编写一个方法,该方法检索与其关联的值(项)最多的键(项),但不知道如何执行此操作,例如:

输入:

myItems.mostValues();

输出:

Item1 is has the most interactions, as it is connected to 3 items: {X, Y, Z}

【问题讨论】:

    标签: java hashmap hashset


    【解决方案1】:

    注意:Sergei 的答案处理 null 并且是 O(n) 使用流。 Sergey的答案输出所有可能的值

    带有排序的流(效率较低) - O(nlogn)

    1. 流式传输元素
    2. sizeSet 反向排序
    3. 获取元素的key(或value直接打印出来)
    4. 如果检索到键,则在 myItems 中查找键并打印值
    myItems.entrySet().stream().filter(e -> e.getValue() != null)
      .sorted((a, b) -> b.getValue().size() - a.getValue().size())
      .findFirst().orElse(new SimpleImmutableEntry<>(null, null))
      .getValue());
    

    正常的 for 循环 - O(n)

    1. 遍历所有整体
    2. 在每次迭代时跟踪最大大小
      int maxItem = 0;
      Set<String> maxValues = null;
      for (Map.Entry<String, Set<String>> e : myItems.entrySet()) {
        if (e.getValue() == null) {
          return null;
        }
        if (maxItem < e.getValue().size()) {
          maxValues = e.getValue();
          maxItem = maxValues.size();
        }
     }
    

    更新:由于答案被接受,我将在 Sergey 和 Sergei 的答案之上添加其他 O(n) 解决方案,处理 null。

    以下代码假设初始 Map 不为空。

    获得最大的一个 - 流 O(n)

    1. 流值
    2. 忽略空值
    3. 获取最大尺寸值(可选)
    4. 如果为空,则返回null
    Map<String, Set<String>> myItems = new HashMap<>(); // input
    myItems.put("a", new HashSet<>(Arrays.asList("a", "b", "c")));
    myItems.put("b", new HashSet<>(Arrays.asList("b", "c")));
    
    Set<String> result = myItems.values().stream()
      .filter(Objects::nonNull) // get only non-null
      .max(Comparator.comparing(Set::size)) // get the max size
      .orElse(null); // avoid optional.get() error incase of no results - can use new HashSet<>() also
    

    流 - 获取所有最大值 - O(n)

    查找最大尺寸(如果没有元素,则为 -1)

    1. 流值
    2. 忽略空值
    3. 将值转换为大小
    4. 找到最大尺寸
    5. 流值
    6. 忽略空值
    7. 选择大小为最大大小的值
    8. 将所有值收集为List
    Map<String, Set<String>> myItems = new HashMap<>(); // input
    myItems.put("a", new HashSet<>(Arrays.asList("a", "b", "c")));
    myItems.put("b", new HashSet<>(Arrays.asList("x", "y", "z")));
    myItems.put("c", new HashSet<>(Arrays.asList("a")));
    
    List<Set<String>> result = new ArrayList<>();
    myItems.values().stream()
      .filter(Objects::nonNull) // get only non-null
      .mapToInt(Set::size)
      .max()
      .ifPresent(val -> myItems.values().stream()
        .filter(Objects::nonNull)
        .filter(v -> v.size() == val)
        .forEach(v -> result.add(v)));
    

    通过 lambda/方法引用使用 Streams

    1. 尽可能尝试使用 :: 的方法引用,因为这有助于在需要时理解对象类型 (Set::size) 并为常见操作抽象类型 (Objects::nonNull)。
    2. 在实际代码中,始终处理 null(即使使用 Optional)

    【讨论】:

    • 不是批评,只是添加信息:上述解决方案都假设值永远不能为空。如果 OP 在他的映射中可以有空值而不是初始化的 HashSet,他将不得不通过在对值调用 size() 之前添加空检查来处理这些情况。
    • @OHGODSPIDERS,感谢您的反馈,我已经用null 检查更新了答案。此外,将通过完整的检查添加任何未来的答案。感谢您抽出宝贵时间检查答案。
    【解决方案2】:
    map.entrySet().stream()
                    .filter(entry -> entry.getValue() != null)
                    .max(Comparator.comparingInt(e -> e.getValue().size()))
                    .map(entry -> map.get(entry.getKey()));
    

    【讨论】:

    • 感谢您分享优化版本(我完全错过了这个)。不过你不需要演员表。
    • 感谢您的指出!我刚刚删除了多余的演员表
    【解决方案3】:
     map.values()
        .stream()
        .filter(Objects::nonNull)
        .mapToInt(val -> val.size())
        .max()
        .ifPresent(val-> map.keySet()
                .stream()
                .filter(key-> map.get(key) != null && map.get(key).size() == val)
                .forEach(System.out::println)
        );
    
    

    【讨论】:

    • 很好,另一个 O(n) 解决方案。根据Sergeis 的回答,您可以在流后添加.filter(Objects::nonNull) 来处理null 以使其成为完整的答案。
    • 谢谢,@Horse,我已经添加了
    • 我认为,您可能还需要在 ifPresent 中添加空检查,否则 map.get(key).size() 可能会抛出 NPE
    • @horse 我检查了
    • @SergeyAfinogenov 比较器中有错字,e2 丢失。 Comparator.comparingInt(e -&gt; e.getValue().size()) 可以使用,因为它不那么冗长
    猜你喜欢
    • 2018-06-18
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2014-03-15
    • 2013-10-16
    • 2014-08-18
    相关资源
    最近更新 更多