web-dev-qa-db-fra.com

Comment trier les valeurs de carte par clé en Java?

J'ai une carte qui a des chaînes pour les clés et les valeurs. 

Les données sont comme suit: 

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

Je veux trier la carte en fonction de ses clés. Donc, au final, j'aurai question1, question2, question3.... et ainsi de suite. 


En fin de compte, j'essaie d'obtenir deux chaînes de cette carte. 

  • Première chaîne: Questions (dans l'ordre 1 ..10)
  • Deuxième chaîne: Réponses (dans le même ordre que la question)

À l'heure actuelle, j'ai les éléments suivants:

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

Cela me donne les questions dans une chaîne, mais elles ne sont pas en ordre.

320
n00bstackie

Réponse courte

Utilisez une TreeMap . C'est précisément ce que c'est. 

Si cette carte vous est transmise et que vous ne pouvez pas déterminer le type, vous pouvez alors procéder comme suit:

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

Cela va parcourir la carte dans l'ordre naturel des touches.


Réponse plus longue

Techniquement, vous pouvez utiliser tout ce qui implémente SortedMap, mais excepté dans de rares cas, cela équivaut à TreeMap, tout comme utiliser une implémentation Map équivaut généralement à HashMap

Dans les cas où vos clés sont d'un type complexe qui n'implémente pas Comparable ou si vous ne souhaitez pas utiliser l'ordre naturel, TreeMap et TreeSet ont des constructeurs supplémentaires qui vous permettent de passer une 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());

Rappelez-vous que lorsque vous utilisez une variable TreeMap ou TreeSet, ses performances seront différentes de celles de HashMap ou HashSet. En gros, les opérations qui trouvent ou insèrent un élément vont de O(1) à O(Log(N)).

Dans une HashMap, passer de 1 000 éléments à 10 000 n'affecte pas vraiment le temps nécessaire pour rechercher un élément, mais pour une TreeMap, le temps de recherche sera environ trois fois plus lent (en supposant que Log2). Passer de 1 000 à 100 000 sera environ 6 fois plus lent pour chaque recherche d'élément.

562
Jherico

En supposant que TreeMap ne soit pas bon pour vous (et en supposant que vous ne pouvez pas utiliser de génériques):

List sortedKeys=new ArrayList(yourMap.keySet());
Collections.sort(sortedKeys);
// Do what you need with sortedKeys.
126
TrayMan

En utilisant TreeMap, vous pouvez trier la carte.

Map<String, String> map = new HashMap<>();        
Map<String, String> treeMap = new TreeMap<>(map);
for (String str : treeMap.keySet()) {
    System.out.println(str);
}
48
Manoj Singh

Utilisez un TreeMap !

34
AgileJon

Si vous avez déjà une carte et souhaitez la trier sur des clés, utilisez simplement:

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

Un exemple de travail complet:

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
32
M-D

Il suffit d'utiliser TreeMap

new TreeMap<String, String>(unsortMap);

Sachez que la TreeMap est triée selon l'ordre naturel de ses 'clés'

28
Aliti

Si vous ne pouvez pas utiliser TreeMap, dans Java 8, nous pouvons utiliser la méthode toMap () dans Collectors qui prend les paramètres suivants:

  • keymapper: fonction de mappage pour produire des clés
  • valuemapper: fonction de mapping pour produire des valeurs
  • mergeFunction: fonction de fusion utilisée pour résoudre les conflits entre les valeurs associées à la même clé.
  • mapSupplier: une fonction qui renvoie une nouvelle carte vide dans laquelle les résultats seront insérés.

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

Nous pouvons modifier l'exemple pour utiliser un comparateur personnalisé et pour trier sur la base des clés comme suit:

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

Utilisation de 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));
6
Taras Melnyk

Ce code peut trier une carte clé-valeur dans les deux ordres, à savoir croissant et décroissant.

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

Par exemple:

Map<Integer,Double> recommWarrVals = new HashMap<Integer,Double>();
recommWarrVals = sortByValues(recommWarrVals, 1);  // Ascending order
recommWarrVals = sortByValues(recommWarrVals,-1);  // Descending order
5
M. Mashaye

En Java 8

Pour trier un Map<K, V> par clé, placez les clés dans un List<K>:

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

Pour trier un Map<K, V> par clé, en plaçant les entrées dans un List<Map.Entry<K, V>>:

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

Dernier point mais non le moindre: pour trier strings en fonction des paramètres régionaux - utilisez une classe Collator (comparateur):

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
Oleksandr
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
Manoj Singh

Nous pouvons également trier la clé en utilisant la méthode Arrays.sort.

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);
}
0
Manoj Singh

Dans un style fonctionnel sera comme ci-dessous:

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

Sortie:

question 1 

question 2

question5

question9

0
Common Man

En Java 8, vous pouvez également utiliser .stream (). Sorted ():

myMap.keySet().stream().sorted().forEach(key -> {
        String value = myMap.get(key);

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