如何 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)
- 流式传输元素
- 按
Set
的 size
反向排序
- 获取元素的key(或者直接value打印出来)
- 如果检索到键,则在 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)
- 遍历所有整体
- 在每次迭代时跟踪最大大小
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)
- 流值
- 忽略空值
- 获取最大尺寸值(可选)
- 如果为空,则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)
- 流值
- 忽略空值
- 将值转换为其大小
- 找到最大尺寸
- 流值
- 忽略空值
- Select 大小为最大大小的值
- 收集所有值作为
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 引用的流
- 尽可能尝试使用使用
::
的方法引用,因为这有助于在需要时理解对象类型 (Set::size
) 并为常见操作抽象类型 (Objects::nonNull
)。
- 在实际代码中,始终处理 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)
);
我目前有一个 'HashMap<String, HashSet>' 形式的 HashMap,其中包含一个键(一个项目)和一个值(与该项目关联的所有项目的 HashSet)。
我正在尝试在 class 中编写一个方法来检索具有最多关联值(项)的键(项),但我不确定如何执行此操作,例如:
输入:
myItems.mostValues();
输出:
Item1 is has the most interactions, as it is connected to 3 items: {X, Y, Z}
注意:
带排序的流(效率较低)- O(nlogn)
- 流式传输元素
- 按
Set
的 - 获取元素的key(或者直接value打印出来)
- 如果检索到键,则在 myItems 中查找键并打印值
size
反向排序
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)
- 遍历所有整体
- 在每次迭代时跟踪最大大小
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)
- 流值
- 忽略空值
- 获取最大尺寸值(可选)
- 如果为空,则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)
- 流值
- 忽略空值
- 将值转换为其大小
- 找到最大尺寸
- 流值
- 忽略空值
- Select 大小为最大大小的值
- 收集所有值作为
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 引用的流
- 尽可能尝试使用使用
::
的方法引用,因为这有助于在需要时理解对象类型 (Set::size
) 并为常见操作抽象类型 (Objects::nonNull
)。 - 在实际代码中,始终处理 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)
);