我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
我对Java比较陌生,经常发现需要对值进行Map<Key,Value>排序。
由于这些值不是唯一的,我发现自己将keySet转换为一个数组,并使用自定义比较器通过数组排序对该数组进行排序,该比较器根据与该键关联的值进行排序。
有没有更简单的方法?
当前回答
好的,这个版本使用两个新的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对象时使用它。
class MyComparator implements Comparator<Object> {
Map<String, Integer> map;
public MyComparator(Map<String, Integer> map) {
this.map = map;
}
public int compare(Object o1, Object o2) {
if (map.get(o2) == map.get(o1))
return 1;
else
return ((Integer) map.get(o2)).compareTo((Integer)
map.get(o1));
}
}
在主函数中使用以下代码
Map<String, Integer> lMap = new HashMap<String, Integer>();
lMap.put("A", 35);
lMap.put("B", 75);
lMap.put("C", 50);
lMap.put("D", 50);
MyComparator comparator = new MyComparator(lMap);
Map<String, Integer> newMap = new TreeMap<String, Integer>(comparator);
newMap.putAll(lMap);
System.out.println(newMap);
输出:
{B=75, D=50, C=50, A=35}
您可以尝试Guava的多功能地图:
TreeMap<Integer, Collection<String>> sortedMap = new TreeMap<>(
Multimaps.invertFrom(Multimaps.forMap(originalMap),
ArrayListMultimap.<Integer, String>create()).asMap());
因此,您将获得从原始值到对应于它们的键集合的映射。即使同一值有多个键,也可以使用此方法。
从…起http://www.programmersheaven.com/download/49349/download.aspx
private static <K, V> Map<K, V> sortByValue(Map<K, V> map) {
List<Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Object>() {
@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
return ((Comparable<V>) ((Map.Entry<K, V>) (o1)).getValue()).compareTo(((Map.Entry<K, V>) (o2)).getValue());
}
});
Map<K, V> result = new LinkedHashMap<>();
for (Iterator<Entry<K, V>> it = list.iterator(); it.hasNext();) {
Map.Entry<K, V> entry = (Map.Entry<K, V>) it.next();
result.put(entry.getKey(), entry.getValue());
}
return result;
}
以下是通用友好版本:
public class MapUtil {
public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
List<Entry<K, V>> list = new ArrayList<>(map.entrySet());
list.sort(Entry.comparingByValue());
Map<K, V> result = new LinkedHashMap<>();
for (Entry<K, V> entry : list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
}
这还有一个额外的好处,即可以使用Java8进行升序或降序排序
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.toMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;
class Utils {
public static Map<String, Integer> sortMapBasedOnValues(Map<String, Integer> map, boolean descending) {
int multiplyBy = (descending) ? -1: 1;
Map<String, Integer> sorted = map.entrySet().stream()
.sorted(comparingInt(e -> multiplyBy * e.getValue() ))
.collect(toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(a, b) -> { throw new AssertionError();},
LinkedHashMap::new
));
return sorted;
}
}