我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
当前回答
如果您的Map值实现Comparable(例如String),那么这应该会起作用
Map<Object, String> map = new HashMap<Object, String>();
// Populate the Map
List<String> mapValues = new ArrayList<String>(map.values());
Collections.sort(mapValues);
如果映射值本身没有实现Comparable,但您有一个Comparable实例可以对它们进行排序,请将最后一行替换为:
Collections.sort(mapValues, comparable);
其他回答
使用LinkedList
//Create a list by HashMap
List<Map.Entry<String, Double>> list = new LinkedList<>(hashMap.entrySet());
//Sorting the list
Collections.sort(list, new Comparator<Map.Entry<String, Double>>() {
public int compare(Map.Entry<String, Double> o1, Map.Entry<String, Double> o2) {
return (o1.getValue()).compareTo(o2.getValue());
}
});
//put data from sorted list to hashmap
HashMap<String, Double> sortedData = new LinkedHashMap<>();
for (Map.Entry<String, Double> data : list) {
sortedData.put(data.getKey(), data.getValue());
}
System.out.print(sortedData);
因为地图是无序的要对其进行排序,我们可以执行以下操作
Map<String, String> map= new TreeMap<String, String>(unsortMap);
您应该注意,与哈希映射不同,树映射保证其元素将按升序键排序。
好的,这个版本使用两个新的Map对象和两次迭代,并对值进行排序。希望,虽然地图条目必须循环两次,但表现良好:
public static void main(String[] args) {
Map<String, String> unsorted = new HashMap<String, String>();
unsorted.put("Cde", "Cde_Value");
unsorted.put("Abc", "Abc_Value");
unsorted.put("Bcd", "Bcd_Value");
Comparator<String> comparer = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}};
System.out.println(sortByValue(unsorted, comparer));
}
public static <K, V> Map<K,V> sortByValue(Map<K, V> in, Comparator<? super V> compare) {
Map<V, K> swapped = new TreeMap<V, K>(compare);
for(Entry<K,V> entry: in.entrySet()) {
if (entry.getValue() != null) {
swapped.put(entry.getValue(), entry.getKey());
}
}
LinkedHashMap<K, V> result = new LinkedHashMap<K, V>();
for(Entry<V,K> entry: swapped.entrySet()) {
if (entry.getValue() != null) {
result.put(entry.getValue(), entry.getKey());
}
}
return result;
}
该解决方案使用带有比较器的TreeMap,并对所有空键和值进行排序。首先,使用TreeMap中的排序功能对值进行排序,然后使用排序后的Map创建一个结果,因为LinkedHashMap保留了相同的值顺序。
格里兹,GHad
在TreeMap中,键按自然顺序排序。例如,如果您对数字进行排序,(注意4的排序)
{0=0, 10=10, 20=20, 30=30, 4=4, 50=50, 60=60, 70=70}
要解决这个问题,在Java8中,首先检查字符串长度,然后进行比较。
Map<String, String> sortedMap = new TreeMap<>Comparator.comparingInt(String::length)
.thenComparing(Function.identity()));
{0=0, 4=4, 10=10, 20=20, 30=30, 50=50, 60=60, 70=70}
当我面对这个问题时,我只是在旁边创建一个列表。如果您将它们放在一个自定义的Map实现中,它会有一种很好的感觉……您可以使用类似以下的方式,仅在需要时执行排序。(注意:我还没有真正测试过这个,但它可以编译……可能是某个地方的一个愚蠢的小bug)
(如果您希望按键和值对其进行排序,请让类扩展TreeMap,不要定义访问器方法,并让赋值函数调用super.xxxxx而不是map_.xxxx)
package com.javadude.sample;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SortedValueHashMap<K, V> implements Map<K, V> {
private Map<K, V> map_ = new HashMap<K, V>();
private List<V> valueList_ = new ArrayList<V>();
private boolean needsSort_ = false;
private Comparator<V> comparator_;
public SortedValueHashMap() {
}
public SortedValueHashMap(List<V> valueList) {
valueList_ = valueList;
}
public List<V> sortedValues() {
if (needsSort_) {
needsSort_ = false;
Collections.sort(valueList_, comparator_);
}
return valueList_;
}
// mutators
public void clear() {
map_.clear();
valueList_.clear();
needsSort_ = false;
}
public V put(K key, V value) {
valueList_.add(value);
needsSort_ = true;
return map_.put(key, value);
}
public void putAll(Map<? extends K, ? extends V> m) {
map_.putAll(m);
valueList_.addAll(m.values());
needsSort_ = true;
}
public V remove(Object key) {
V value = map_.remove(key);
valueList_.remove(value);
return value;
}
// accessors
public boolean containsKey(Object key) { return map_.containsKey(key); }
public boolean containsValue(Object value) { return map_.containsValue(value); }
public Set<java.util.Map.Entry<K, V>> entrySet() { return map_.entrySet(); }
public boolean equals(Object o) { return map_.equals(o); }
public V get(Object key) { return map_.get(key); }
public int hashCode() { return map_.hashCode(); }
public boolean isEmpty() { return map_.isEmpty(); }
public Set<K> keySet() { return map_.keySet(); }
public int size() { return map_.size(); }
public Collection<V> values() { return map_.values(); }
}