1890 Stimmen

Sortieren einer Map<Schlüssel, Wert> nach Werten

Ich bin relativ neu in Java und stelle oft fest, dass ich eine Map<Key, Value> auf die Werte.

Da die Werte nicht eindeutig sind, muss ich die keySet in eine array und die Sortierung dieses Arrays durch Array-Sortierung mit einer benutzerdefinierter Komparator die nach dem mit dem Schlüssel verbundenen Wert sortiert.

Gibt es einen einfacheren Weg?

6voto

avi Punkte 61

Einfacher Weg zum Sortieren einer Karte in Java 8 und höher

Map<String, Object> mapToSort = new HashMap<>();

List<Map.Entry<String, Object>> list = new LinkedList<>(mapToSort.entrySet());

Collections.sort(list, Comparator.comparing(o -> o.getValue().getAttribute()));

HashMap<String, Object> sortedMap = new LinkedHashMap<>();
for (Map.Entry<String, Object> map : list) {
   sortedMap.put(map.getKey(), map.getValue());
}

wenn Sie Java 7 und darunter verwenden

Map<String, Object> mapToSort = new HashMap<>();

List<Map.Entry<String, Object>> list = new LinkedList<>(mapToSort.entrySet());

Collections.sort(list, new Comparator<Map.Entry<String, Object>>() {
    @Override
    public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
       return o1.getValue().getAttribute().compareTo(o2.getValue().getAttribute());      
    }
});

HashMap<String, Object> sortedMap = new LinkedHashMap<>();
for (Map.Entry<String, Object> map : list) {
   sortedMap.put(map.getKey(), map.getValue());
}

5voto

lisak Punkte 20709

Afaik der sauberste Weg ist die Verwendung von Sammlungen zu sortieren Karte auf Wert:

Map<String, Long> map = new HashMap<String, Long>();
// populate with data to sort on Value
// use datastructure designed for sorting

Queue queue = new PriorityQueue( map.size(), new MapComparable() );
queue.addAll( map.entrySet() );

// get a sorted map
LinkedHashMap<String, Long> linkedMap = new LinkedHashMap<String, Long>();

for (Map.Entry<String, Long> entry; (entry = queue.poll())!=null;) {
    linkedMap.put(entry.getKey(), entry.getValue());
}

public static class MapComparable implements Comparator<Map.Entry<String, Long>>{

  public int compare(Entry<String, Long> e1, Entry<String, Long> e2) {
    return e1.getValue().compareTo(e2.getValue());
  }
}

5voto

Darkless Punkte 11

Das ist einfach zu kompliziert. Die Karten sollten nicht die Aufgabe haben, sie nach Wert zu sortieren. Am einfachsten ist es, eine eigene Klasse zu erstellen, die Ihren Anforderungen entspricht.

Im unteren Beispiel sollen Sie TreeMap an der Stelle, an der * steht, einen Komparator hinzufügen. Aber durch Java-API gibt es Komparator nur Schlüssel, nicht Werte. Alle hier genannten Beispiele basieren auf 2 Maps. Ein Hash und ein neuer Tree. Das ist seltsam.

Das Beispiel:

Map<Driver driver, Float time> map = new TreeMap<Driver driver, Float time>(*);

Ändern Sie also die Karte auf diese Weise in ein Set:

ResultComparator rc = new ResultComparator();
Set<Results> set = new TreeSet<Results>(rc);

Sie werden die Klasse Results ,

public class Results {
    private Driver driver;
    private Float time;

    public Results(Driver driver, Float time) {
        this.driver = driver;
        this.time = time;
    }

    public Float getTime() {
        return time;
    }

    public void setTime(Float time) {
        this.time = time;
    }

    public Driver getDriver() {
        return driver;
    }

    public void setDriver (Driver driver) {
        this.driver = driver;
    }
}

und die Klasse Comparator:

public class ResultsComparator implements Comparator<Results> {
    public int compare(Results t, Results t1) {
        if (t.getTime() < t1.getTime()) {
            return 1;
        } else if (t.getTime() == t1.getTime()) {
            return 0;
        } else {
            return -1;
        }
    }
}

Auf diese Weise können Sie leicht weitere Abhängigkeiten hinzufügen.

Und als letzten Punkt werde ich einen einfachen Iterator hinzufügen:

Iterator it = set.iterator();
while (it.hasNext()) {
    Results r = (Results)it.next();
    System.out.println( r.getDriver().toString
        //or whatever that is related to Driver class -getName() getSurname()
        + " "
        + r.getTime()
        );
}

5voto

cuneyt Punkte 1

Ein großes Problem. Wenn Sie die erste Antwort verwenden (Google führt Sie hierher), ändern Sie den Komparator, um eine Gleichheitsklausel hinzuzufügen, da Sie sonst keine Werte aus der sort_map nach Schlüsseln erhalten können:

public int compare(String a, String b) {
        if (base.get(a) > base.get(b)) {
            return 1;
        } else if (base.get(a) < base.get(b)){
            return -1;
        } 

        return 0;
        // returning 0 would merge keys
    }

5voto

Supreet Singh Punkte 636

Dies könnte sehr einfach mit Java 8 erreicht werden

public static LinkedHashMap<Integer, String> sortByValue(HashMap<Integer, String> map) {

        List<Map.Entry<Integer, String>> list = new ArrayList<>(map.entrySet());
        list.sort(Map.Entry.comparingByValue());
        LinkedHashMap<Integer, String> sortedMap = new LinkedHashMap<>();
        list.forEach(e -> sortedMap.put(e.getKey(), e.getValue()));
        return sortedMap;
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X