Как отсортировать значения карты по ключу в Java? - PullRequest
330 голосов
/ 28 мая 2009

У меня есть карта, в которой есть строки для ключей и значений.

Данные выглядят следующим образом:

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

Я хочу отсортировать карту по ключам. Итак, в итоге у меня будет question1, question2, question3 .... и так далее.


В конце концов, я пытаюсь получить две строки из этой карты.

  • Первая строка: Вопросы (в порядке 1 ..10)
  • Вторая строка: ответы (в том же порядке, что и вопрос)

Сейчас у меня есть следующее:

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

Это приводит меня к вопросам в строке, но они не в порядке.

Ответы [ 13 ]

575 голосов
/ 28 мая 2009

Краткий ответ

Используйте TreeMap. Это именно то, для чего это.

Если эта карта передана вам, и вы не можете определить тип, то вы можете сделать следующее:

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

Это будет проходить по карте в естественном порядке ключей.


Более длинный ответ

Технически, вы можете использовать все, что реализует SortedMap, но за исключением редких случаев это составляет TreeMap, так же как использование Map обычно составляет HashMap.

Для случаев, когда ваши ключи являются сложным типом, который не реализует Comparable, или вы не хотите использовать естественный порядок, тогда TreeMap и TreeSet имеют дополнительные конструкторы, которые позволяют вам передавать Comparator:

// 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());

Помните, что при использовании TreeMap или TreeSet производительность будет отличаться от HashMap или HashSet. Грубо говоря, операции по поиску или вставке элемента будут идти от O (1) до O (Log (N)) .

В HashMap переход от 1000 элементов к 10000 на самом деле не влияет на ваше время поиска элемента, но для TreeMap время поиска будет примерно в 3 раза медленнее (при условии Log 2 ). Перемещение от 1000 до 100 000 будет примерно в 6 раз медленнее для каждого поиска элемента.

127 голосов
/ 28 мая 2009

Если предположить, что TreeMap вам не подходит (и что вы не можете использовать дженерики):

List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.
49 голосов
/ 07 ноября 2011

С помощью TreeMap вы можете отсортировать карту.

Map<String, String> map = new HashMap<>();        
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
    System.out.println(str);
}
34 голосов
/ 21 августа 2013

Если у вас уже есть карта и вы хотите отсортировать ее по ключам, просто используйте:

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

Полный рабочий пример:

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
34 голосов
/ 28 мая 2009

Используйте TreeMap !

29 голосов
/ 18 февраля 2015

Просто используйте TreeMap

new TreeMap<String, String>(unsortMap);

Помните, что TreeMap сортируется в соответствии с естественным порядком его «ключей»

12 голосов
/ 17 ноября 2016

При условии, что вы не можете использовать TreeMap, в Java 8 мы можем использовать метод toMap () в Collectors, который принимает следующие параметры:

  • keymapper : функция отображения для создания ключей
  • valuemapper : функция отображения для получения значений
  • mergeFunction : функция слияния, используемая для разрешить конфликты между значениями, связанными с одним и тем же ключом
  • mapSupplier : функция, которая возвращает новую пустую карту, в которую результаты будут вставлены.

Пример Java 8

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));

Мы можем изменить пример для использования собственного компаратора и сортировки по ключам следующим образом:

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));
7 голосов
/ 01 мая 2018

Использование Java 8:

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));
5 голосов
/ 14 апреля 2018

В Java 8

Чтобы отсортировать Map<K, V> по ключу, поместите ключи в List<K>:

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

Чтобы отсортировать Map<K, V> по ключу, поместите записи в List<Map.Entry<K, V>>:

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

Последнее, но не менее важное: для сортировки строк с учетом языка - используйте класс Collator (компаратор):

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());
5 голосов
/ 24 ноября 2015

Этот код может сортировать карту значений ключей в обоих порядках, то есть по возрастанию и по убыванию.

<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;
}

Как пример:

Map<Integer,Double> recommWarrVals = new HashMap<Integer,Double>();
recommWarrVals = sortByValues(recommWarrVals, 1);  // Ascending order
recommWarrVals = sortByValues(recommWarrVals,-1);  // Descending order
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...