我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
当前回答
最干净的方法是利用集合对值进行排序:
Map<String, Long> map = new HashMap<String, Long>();
// populate with data to sort on Value
// use datastructure designed for sorting
Queue queue = new PriorityQueue( map.size(), new MapComparable() );
queue.addAll( map.entrySet() );
// get a sorted map
LinkedHashMap<String, Long> linkedMap = new LinkedHashMap<String, Long>();
for (Map.Entry<String, Long> entry; (entry = queue.poll())!=null;) {
linkedMap.put(entry.getKey(), entry.getValue());
}
public static class MapComparable implements Comparator<Map.Entry<String, Long>>{
public int compare(Entry<String, Long> e1, Entry<String, Long> e2) {
return e1.getValue().compareTo(e2.getValue());
}
}
其他回答
使用Guava库:
public static <K,V extends Comparable<V>>SortedMap<K,V> sortByValue(Map<K,V> original){
var comparator = Ordering.natural()
.reverse() // highest first
.nullsLast()
.onResultOf(Functions.forMap(original, null))
.compound(Ordering.usingToString());
return ImmutableSortedMap.copyOf(original, comparator);
}
这是Anthony答案的变体,如果存在重复值,则该答案无效:
public static <K, V extends Comparable<V>> Map<K, V> sortMapByValues(final Map<K, V> map) {
Comparator<K> valueComparator = new Comparator<K>() {
public int compare(K k1, K k2) {
final V v1 = map.get(k1);
final V v2 = map.get(k2);
/* Not sure how to handle nulls ... */
if (v1 == null) {
return (v2 == null) ? 0 : 1;
}
int compare = v2.compareTo(v1);
if (compare != 0)
{
return compare;
}
else
{
Integer h1 = k1.hashCode();
Integer h2 = k2.hashCode();
return h2.compareTo(h1);
}
}
};
Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
sortedByValues.putAll(map);
return sortedByValues;
}
注意,如何处理空值还很难说。
这种方法的一个重要优点是它实际上返回了一个Map,这与这里提供的其他解决方案不同。
用Java中最简单的方式对任何Hashmap进行排序。我们不需要将其存储在树图、列表等中。
在这里,我将使用Java Streams:
让我们按其值(升序)对该地图进行排序
Map<String, Integer> mp= new HashMap<>();
mp.put("zebra", 1);
mp.put("blossom", 2);
mp.put("gemini", 3);
mp.put("opera", 7);
mp.put("adelaide", 10);
Map<String, Integer> resultMap= mp.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e1, LinkedHashMap::new));
现在,您可以通过多种方式打印排序后的resultMap,例如使用高级for循环或迭代器。
上面的映射也可以按值的降序排序
Map<String, Integer> resultMap= mp.entrySet().stream().sorted(Map.Entry.<String, Integer>comparingByValue().reversed()).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e1, LinkedHashMap::new));
现在让我们来看另一个场景,我们将“User”存储在地图中,并根据“User”的“name”按升序(词典)对其进行排序:
User u1= new User("hi", 135);
User u2= new User("bismuth", 900);
User u3= new User("alloy", 675);
User u4= new User("jupiter", 342);
User u5= new User("lily", 941);
Map<String, User> map2= new HashMap<>();
map2.put("zebra", u3);
map2.put("blossom", u5);
map2.put("gemini", u1);
map2.put("opera", u2);
map2.put("adelaide", u4);
Map<String, User> resultMap=
map2.entrySet().stream().sorted(Map.Entry.<String, User>comparingByValue( (User o1, User o2)-> o1.getName().compareTo(o2.getName()))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,(e1, e2) -> e2, LinkedHashMap::new));
class User
{
String name;
int id;
public User(String name, int id) {
super();
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "User [name=" + name + ", id=" + id + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
以下是Java8的代码,使用算盘
Map<String, Integer> map = N.asMap("a", 2, "b", 3, "c", 1, "d", 2);
Map<String, Integer> sortedMap = Stream.of(map.entrySet()).sorted(Map.Entry.comparingByValue()).toMap(e -> e.getKey(), e -> e.getValue(),
LinkedHashMap::new);
N.println(sortedMap);
// output: {c=1, a=2, d=2, b=3}
声明:我是算盘通用的开发者。
迟到。
随着Java-8的出现,我们可以以非常简单/简洁的方式使用流进行数据操作。您可以使用流按值对映射条目进行排序,并创建一个LinkedHashMap,以保留插入顺序迭代。
Eg:
LinkedHashMap sortedByValueMap = map.entrySet().stream()
.sorted(comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey)) //first sorting by Value, then sorting by Key(entries with same value)
.collect(LinkedHashMap::new,(map,entry) -> map.put(entry.getKey(),entry.getValue()),LinkedHashMap::putAll);
对于反向排序,请替换:
comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey)
with
comparing(Entry<Key,Value>::getValue).thenComparing(Entry::getKey).reversed()