2015-04-25 6 views

Antwort

0

Da Java 1,8 java.util.Comparator.reversed()

myMap.entrySet().stream() 
.sorted(Map.Entry.comparingByValue().reversed()) 
.collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 
5

Sie können den gewünschten Komparator comparingByValue übergeben.

Zum Beispiel (ich hoffe, dass ich die Syntax richtig verstanden habe, da ich es nicht testen):

myMap.entrySet().stream() 
    .sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1))) 
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); 

Durch den Vergleich der Werte der beiden Einträge in umgekehrter Reihenfolge, die natürliche Ordnung mit (Comparable 's compareTo), erhalten Sie eine umgekehrte Reihenfolge im Vergleich zu was comparingByValue() (was comparingByValue((v1,v2)->v1.compareTo(v2)) entspricht) geben Ihnen.

BTW, Ich bin mir nicht sicher, dass Collectors.toMap eine Instanz zurückgibt, und selbst wenn es derzeit tut, kann es in der Zukunft ändern, da der Javadoc es nicht erwähnt, so dass Sie sich nicht darauf verlassen können.

Um sicherzustellen, dass die resultierende Karte ein LinkedHashMap sein würde, Sie eine andere Variante von toMap verwenden sollten:

myMap.entrySet().stream() 
    .sorted(Map.Entry.comparingByValue((v1,v2)->v2.compareTo(v1))) 
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (v1,v2)->v1, LinkedHashMap::new)); 
+1

Wie der Name ('comparingByValue') zeigt, ist der Typparameter des Lambda-Ausdrucks' v' nicht 'Eintrag 'weil Sie einen Komparator für die Werte bereitstellen, so dass Sie ihn in' comparingByValue ((v1, v2) -> v2.compareTo (v1)) '' oder besser 'comparingByValue (reverseOrder())' ändern können, wie von @Misha vorgeschlagen ... –

+0

..und wie Sie gesagt haben, einen schnellen Blick auf den Quellcode von 'toMap' Sie sehen, dass es zurückgibt' toMap (keyMapper, valueMapper, werfenderMerger(), HashMap :: new); '. Also im Grunde wird Ihre Implementierung nichts sehr nützliches tun (obwohl Sie es aus der OP-Frage genommen haben) ... –

+1

@AlexisC. Danke für den Kommentar. Das habe ich total vermisst. Das passiert, wenn ich Code schreibe, ohne zu versuchen, ihn zu kompilieren. – Eran

25

zu sortieren in umgekehrter Reihenfolge, Comparator.reverseOrder() als Parameter comparingByValue passieren.

Um eine zu erhalten, müssen Sie speziell eine mit dem 4-Argument toMap() anfordern. Wenn Sie nicht angeben, welche Art von Karte Sie wollen, erhalten Sie, was auch immer der Standard ist, der momentan ein HashMap ist. Da HashMap nicht die Reihenfolge der Elemente bewahrt, wird es definitiv nicht für Sie tun.

myMap.entrySet().stream() 
     .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 
     .collect(Collectors.toMap(
       Map.Entry::getKey, 
       Map.Entry::getValue, 
       (x,y)-> {throw new AssertionError();}, 
       LinkedHashMap::new 
     )); 

Bei statischen Importen, wird es etwas angenehmer:

myMap.entrySet().stream() 
     .sorted(comparingByValue(reverseOrder())) 
     .collect(toMap(
       Map.Entry::getKey, 
       Map.Entry::getValue, 
       (x,y)-> {throw new AssertionError();}, 
       LinkedHashMap::new 
     )); 
+0

Diese Antwort ist die einzig gültige. –

+0

Danke, ich wusste nicht, dass ich diesen Comparator.reverserOrder() verwenden könnte. In der Tat dachte ich, dass würde eine direkte Möglichkeit, dies zu tun, wie .sorted (Map.Entry.comparingByValueReverse()) – Oxydron

3

Strom hat als sorted Methode, die Sie direkt in den Komparator als (x,y)->y.getKey().compareTo(x.getKey()) für absteigende Sortierung können daher einen Komparator akzeptiert. Um die Karte in aufsteigend sortieren wir die Bestellung als (x,y)->x.getKey().compareTo(y.getKey())

zur Konsolidierung Ergebnis zurück in LinkedHashMap umkehren können wir Collectors verwenden toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) die eine Collector zurück, die Elemente in eine Karte, deren Schlüssel und Werte sind das Ergebnis der Anwendung sammelt die stellten den Eingabeelementen Zuordnungsfunktionen zur Verfügung.

Arbeits Code

import java.io.*; 
import java.util.*; 
import java.util.function.*; 
import java.util.stream.Collectors; 
import java.util.stream.*; 
public class HelloWorld{ 

    public static void main(String []args){ 
     LinkedHashMap<Integer,Integer> hashMap = new LinkedHashMap<Integer,Integer>(); 
      hashMap.put(1,5); 
      hashMap.put(7,9); 
      hashMap.put(3,8); 
      hashMap.put(10,5); 

      Function<Map.Entry<Integer,Integer>,Integer> keyMapper = x->x.getKey(); 
      Function<Map.Entry<Integer,Integer>,Integer> valueMapper = x->x.getValue(); 
      BinaryOperator< Integer> mergeFunction = (x,y)->x;// we do not want any merging here 
      Supplier<LinkedHashMap<Integer,Integer>> mapRequired =()-> {return new LinkedHashMap<Integer,Integer>();};// to maintain order we must use LinkedHashMap 
      Comparator<Map.Entry<Integer,Integer>> descendingComparator = (x,y)->y.getKey().compareTo(x.getKey()); 
      // we can write it as 

     System.out.println(
        hashMap.entrySet().stream() 
          .sorted (descendingComparator) 
          .collect(Collectors.toMap(
                 keyMapper, 
                 valueMapper, 
                 mergeFunction, 
                 mapRequired) 
              ) 
       );   

// or even by writing below will also work 

     System.out.println(
        hashMap.entrySet().stream() 
          .sorted ((x,y)->y.getKey().compareTo(x.getKey())) 
          .collect(Collectors.toMap(
                 x->x.getKey(), 
                 x->x.getValue(), 
                 (x,y)->x, 
                 LinkedHashMap::new) 
              ) 
       );   
    } 


} 
Verwandte Themen