如何 return HashMap 中关联值最多的键

How to return the key with the most associated values inside a HashMap

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

我正在尝试在 class 中编写一个方法来检索具有最多关联值(项)的键(项),但我不确定如何执行此操作,例如:

输入:

myItems.mostValues();

输出:

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

注意:'s answer handles null and is O(n) using streams. 的答案输出所有可能的值

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

  1. 流式传输元素
  2. Set
  3. size 反向排序
  4. 获取元素的key(或者直接value打印出来)
  5. 如果检索到键,则在 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) 解决方案。

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

获取最大单流 O(n)

  1. 流值
  2. 忽略空值
  3. 获取最大尺寸值(可选)
  4. 如果为空,则return为空
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. Select 大小为最大大小的值
  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/method 引用的流

  1. 尽可能尝试使用使用 :: 的方法引用,因为这有助于在需要时理解对象类型 (Set::size) 并为常见操作抽象类型 (Objects::nonNull)。
  2. 在实际代码中,始终处理 null(即使使用 Optional)
map.entrySet().stream()
                .filter(entry -> entry.getValue() != null)
                .max(Comparator.comparingInt(e -> e.getValue().size()))
                .map(entry -> map.get(entry.getKey()));
 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)
    );