2016-12-16 1 views
4

J'ai une carte et j'ai besoin de trier la clé en fonction de plusieurs conditions. Comment y parvenir en utilisant Java 8 Comparator et Stream?Comment utiliser plusieurs comparateurs sur une carte et des propriétés de valeur avec Java 8

class MyObject { 
    private Set<Objects> setOfStuff; 
    public Set<Objects> getSetOfStuff(){ 
     return listOfStuff; 
    } 
    public int countStuff(){ 
     return listOfStuff.size(); 
    } 
} 

Map<String, List<MyObject> needsSorting = new HashMap<>(); 
needsSorting.put("Monday", createSetOfObj()); 
needsSorting.put("Wednesday", createSetOfObj()); 
needsSorting.put("Thursday", createSetOfObj()); 

Set<MyObject> createSetOfObj() { 
... 
    return list; 
} 

Map<String, Set<MyObject>> sortedResult = new LinkedHashMap<>(); 
  1. Trier par clé, par ordre alphabétique
  2. clé Trier en fonction de la taille de List<MyObject>
  3. Trier clés en fonction de la taille de la plus grande MyObject countStuff();

sinon, il y une meilleure approche ?

Mise à jour 1:

Je pense avoir 1 & 2 fait. Tout simplement pas sûr de savoir comment faire 3.

Comparator<Entry<String, List<MyObject>>> comparator = Comparator.comparing(Map.Entry<String, List<MyObject>>::getKey) 
      .thenComparingInt(e -> e.getValue().size()); 

Mise à jour 2:

Cela semble produire la comparaison dont je avais besoin. J'ai ajouté un countStuff pour un accès facile.

Comparator<Entry<String, Set<MyObject>>> comparator = Comparator.comparing(Map.Entry<String, Set<MyObject>>::getKey) 
      .thenComparingInt(e -> e.getValue().size()) 
      .thenComparingInt(e -> e.getValue().stream().map(MyObject::countStuff).max(Integer::max).get()); 
+2

Pouvez-vous clarifier ce que 'List .getListOfStuff()' est supposé faire? Pourrait-il être réécrit, par exemple, comme 'list.stream(). Filter (...). Count()' où 'list' est de type' Liste '? –

+1

Donc, vous voulez trier une carte par une condition de tri complexe, d'abord par la clé, puis par les attributs de valeur (taille de la liste, plus grand)? Étant donné que la carte d'origine est un 'HashMap', les clés doivent être uniques; ils ne peuvent jamais être égaux, il ne sera donc jamais nécessaire de vérifier les conditions de tri secondaires. – AJNeufeld

+0

'Comparator.comparing (Map.Entry > :: getKey' =>' Entrée :: comparisonByKey' – assylias

Répondre

1

Le HashMap n'est pas idéal pour le tri, vous pouvez utiliser un TreeMap à la place, et passez votre comparateur au constructeur:

SortedMap<String, List<MyObject>> sorted = new TreeMap<>(comparator); 

Edit: le comparateur ne fonctionne que pour les clés non valeurs