关于字典:如何在Java中用键对map值进行排序?

How to sort Map values by key in Java?

我有一个包含键和值字符串的映射。

数据如下:

"question1","1"
"question9","1"
"question2","4"
"question5","2"

我想根据地图的键对其进行排序。所以,最后,我会让question1, question2, question3等等。

最后,我想从这张地图中找出两条线。

  • 第一个字符串:问题(顺序1..10)
  • 第二个字符串:答案(与问题的顺序相同)

现在我有以下内容:

1
2
3
4
5
Iterator it = paramMap.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry pairs = (Map.Entry) it.next();
    questionAnswers += pairs.getKey() +",";
}

这使我的问题成了一个字符串,但它们不按顺序排列。


简短回答

使用TreeMap。这正是它的目的。

如果将此映射传递给您,但您无法确定类型,则可以执行以下操作:

1
2
3
4
5
SortedSet<String> keys = new TreeSet<>(map.keySet());
for (String key : keys) {
   String value = map.get(key);
   // do something
}

这将按键的自然顺序在映射中迭代。

更长的答案

从技术上讲,您可以使用实现SortedMap的任何东西,但除了极少数情况外,这相当于TreeMap,就像使用Map实现通常相当于HashMap一样。

如果您的密钥是一个复杂类型,不实现可比较的或不想使用自然顺序,那么TreeMapTreeSet具有额外的构造函数,允许您在Comparator中传递:

1
2
3
4
5
6
7
// placed inline for the demonstration, but doesn't have to be a lambda expression
Comparator<Foo> comparator = (Foo o1, Foo o2) -> {
        ...
    }

SortedSet<Foo> keys = new TreeSet<>(comparator);
keys.addAll(map.keySet());

记住,当使用TreeMapTreeSet时,它将具有与HashMapHashSet不同的性能特征。大致来说,查找或插入元素的操作将从O(1)转到O(log(n))。

HashMap中,从1000项移动到10000项并不真正影响您查找元素的时间,但对于TreeMap而言,查找时间将慢3倍(假设log2)。对于每个元素查找,从1000到100000的移动速度大约是6倍。


假设treemap对您不好(并且假设您不能使用泛型):

1
2
3
List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.


使用TreeMap可以对地图进行排序。

1
2
3
4
5
Map<String, String> map = new HashMap<>();        
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
    System.out.println(str);
}


使用树形图!


如果您已经有了一个映射,并且希望在键上对其进行排序,只需使用:

1
Map<String, String> treeMap = new TreeMap<String, String>(yourMap);

完整的工作示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.HashMap;
import java.util.Set;
import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;

class SortOnKey {

public static void main(String[] args) {
   HashMap<String,String> hm = new HashMap<String,String>();
   hm.put("3","three");
   hm.put("1","one");
   hm.put("4","four");
   hm.put("2","two");
   printMap(hm);
   Map<String, String> treeMap = new TreeMap<String, String>(hm);
   printMap(treeMap);
}//main

public static void printMap(Map<String,String> map) {
    Set s = map.entrySet();
    Iterator it = s.iterator();
    while ( it.hasNext() ) {
       Map.Entry entry = (Map.Entry) it.next();
       String key = (String) entry.getKey();
       String value = (String) entry.getValue();
       System.out.println(key +" =>" + value);
    }//while
    System.out.println("========================");
}//printMap

}//class

只需使用treemap

1
new TreeMap<String, String>(unsortMap);

注意treemap是按照其"keys"的自然顺序排序的。


如果您不能使用EDCOX1,0,在Java 8中,我们可以在EDCOX1(16)中使用ToMaP()方法,它采用以下参数:

  • keymapper:生成键的映射函数
  • ValueMapper:映射函数以生成值
  • 合并函数:合并函数,用于解决与同一键关联的值之间的冲突
  • mapsupplier:返回新的空映射的函数,其中将插入结果。

Java 8示例

1
2
3
4
5
6
7
Map<String,String> sample = new HashMap<>();  // push some values to map  
Map<String, String> newMapSortedByKey = sample.entrySet().stream()
                    .sorted(Map.Entry.<String,String>comparingByKey().reversed())
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
Map<String, String> newMapSortedByValue = sample.entrySet().stream()
                        .sorted(Map.Entry.<String,String>comparingByValue().reversed())
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));

我们可以修改示例以使用自定义比较器,并根据键进行排序,如下所示:

1
2
3
Map<String, String> newMapSortedByKey = sample.entrySet().stream()
                .sorted((e1,e2) -> e1.getKey().compareTo(e2.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1,e2) -> e1, LinkedHashMap::new));

使用Java 8:

1
2
3
4
Map<String, Integer> sortedMap = unsortMap.entrySet().stream()
            .sorted(Map.Entry.comparingByKey())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (oldValue, newValue) -> oldValue, LinkedHashMap::new));

在Java 8中

要按键对Map进行排序,请将键放入List中:

1
List<K> result = map.keySet().stream().sorted().collect(Collectors.toList());

按键对Map排序,将条目放入List>中:

1
2
3
4
5
List<Map.Entry<K, V>> result =
    map.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByKey())
       .collect(Collectors.toList());

最后但并非最不重要的一点:要以对区域设置敏感的方式对字符串排序,请使用collator(comparator)类:

1
2
3
4
5
6
7
8
Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.PRIMARY); // case insensitive collator

List<Map.Entry<String, String>> result =
    map.entrySet()
       .stream()
       .sorted(Map.Entry.comparingByKey(collator))
       .collect(Collectors.toList());

此代码可以按升序和降序对键值映射进行排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<K, V extends Comparable<V>> Map<K, V> sortByValues
     (final Map<K, V> map, int ascending)
{
     Comparator<K> valueComparator =  new Comparator<K>() {        
        private int ascending;
        public int compare(K k1, K k2) {
            int compare = map.get(k2).compareTo(map.get(k1));
            if (compare == 0) return 1;
            else return ascending*compare;
        }
        public Comparator<K> setParam(int ascending)
        {
            this.ascending = ascending;
            return this;
        }
    }.setParam(ascending);

    Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator);
    sortedByValues.putAll(map);
    return sortedByValues;
}

举个例子:

1
2
3
Map<Integer,Double> recommWarrVals = new HashMap<Integer,Double>();
recommWarrVals = sortByValues(recommWarrVals, 1);  // Ascending order
recommWarrVals = sortByValues(recommWarrVals,-1);  // Descending order

1
2
3
4
5
6
7
8
9
List<String> list = new ArrayList<String>();
Map<String, String> map = new HashMap<String, String>();
for (String str : map.keySet()) {
 list.add(str);
}
Collections.sort(list);
for (String str : list) {
 System.out.println(str);
}


功能风格如下:

1
2
3
4
5
6
7
8
9
 Map<String , String> nameMap = new HashMap<>();
        nameMap.put("question1","1");
        nameMap.put("question9","1");
        nameMap.put("question2","4");
        nameMap.put("question5","2");
        nameMap.entrySet().stream()
            .sorted(Comparator.comparing(x->x.getKey()))
            .map(x->x.getKey())
            .forEach(System.out::println);

输出:

question1

question2

question5

question9


在Java 8中,还可以使用.Stand()。

1
2
3
4
5
6
7
myMap.keySet().stream().sorted().forEach(key -> {
        String value = myMap.get(key);

        System.out.println("key:" + key);
        System.out.println("value:" + value);
    }
);

我们还可以使用array.sort方法对键进行排序。

1
2
3
4
5
6
7
8
9
Map<String, String> map = new HashMap<String, String>();
Object[] objArr = new Object[map.size()];
for (int i = 0; i < map.size(); i++) {
objArr[i] = map.get(i);
}
Arrays.sort(objArr);
for (Object str : objArr) {
System.out.println(str);
}