是否有方法(可能使用Google Collections)获取Map(Key, Double)
的最小值?
在传统方式中,我必须根据值对地图进行排序,并采用第一个/最后一个。
你可以使用标准的Collections#min()
。
Map<String, Double> map = new HashMap<String, Double>();
map.put("1.1", 1.1);
map.put("0.1", 0.1);
map.put("2.1", 2.1);
Double min = Collections.min(map.values());
System.out.println(min); // 0.1
更新:因为你也需要密钥,好吧,我没有在Collections
或Google Collections2
API中看到方法,因为Map
不是Collection
。 Maps#filterEntries()
也没有用,因为你只知道迭代结束时的实际结果。
最简单的解决方案就是:
Entry<String, Double> min = null;
for (Entry<String, Double> entry : map.entrySet()) {
if (min == null || min.getValue() > entry.getValue()) {
min = entry;
}
}
System.out.println(min.getKey()); // 0.1
(对qazxsw poi的空检查留在一边)
您仍然可以使用min
和自定义Collections.min
来获得具有较低值的Comparator
:
Map.Entry
使用Java 8:
Map<String, Double> map = new HashMap<String, Double>();
map.put("1.1", 1.1);
map.put("0.1", 0.1);
map.put("2.1", 2.1);
Entry<String, Double> min = Collections.min(map.entrySet(), new Comparator<Entry<String, Double>>() {
public int compare(Entry<String, Double> entry1, Entry<String, Double> entry2) {
return entry1.getValue().compareTo(entry2.getValue());
}
});
System.out.printf("%s: %f", min.getKey(), min.getValue()); // 0.1: 0.100000
以传统方式,我必须根据值对地图进行排序,并采用第一个/最后一个。谢谢
不,你不会。您必须遍历所有值,并在每个步骤中将当前元素与目前为止看到的最小元素进行比较。那是O(n),与O(n * log(n))进行排序相比 - 可能存在巨大差异。
顺便说一句,这正是Entry<String, Double> min = Collections.min(map.entrySet(),
Comparator.comparing(Entry::getValue));
的工作原理。
使用Java 8流:
Collections.min()
要么
return map
.entrySet()
.stream()
.sorted(Comparator.comparingDouble(Map.Entry::getValue))
.findFirst()
.map(Map.Entry::getValue);
但是,如果你想多次这样做,那么一定要给return map
.entrySet()
.stream()
.min(Comparator.comparingDouble(Map.Entry::getValue))
.map(Map.Entry::getValue);
看看。
为了有效地执行它,您可能希望定义自己的数据结构,以便它实现Map接口,但也允许有效的getMin()操作。
这可以使用两个内部数据结构来完成:映射和树(或堆数据结构)。每次添加新对(K,V)时,将它们添加到地图中,也添加到树中(作为单个条目)。这允许获得(键)操作O(1)时间,以及添加,删除和getMin操作的O(log n)时间。
使用java 8(和静态导入)。我们可以让@ superfav的解决方案更加整洁:
String minKey = HashBiMap.create(map).inverse().get(Collections.min(map.values()));
在Java 8中,我们可以轻松获得:
Map<String, Double> myMap;
String theKeyWithHighestValue = Collections.min(myMap.entrySet(), comparingDouble(Entry::getValue)).getKey()
Java8 One-Liner
Double minValue = map.entrySet().stream().min(Map.Entry.comparingByValue()).get().getValue();
Double maxValue = map.entrySet().stream().max(Map.Entry.comparingByValue()).get().getValue();