4

J'essaie de trier un flux par un ordre spécifique par l'un de ses champs.Trier Java comme commutateur de type conditionnel

Maintenant, je suis parvenir en convertissant les flux à la liste et à l'aide d'un commutateur, puis les rejoindre dans une liste dans l'ordre souhaité.

 

    fruits.forEach(fruit -> { 
       switch (fruit.getName()) { 
        case "Orange": 
         orangesList.add(fruit); 
         break; 
        case "Apple": 
         applesList.add(fruit); 
         break; 
        case "WaterMelon": 
         watermelonList.add(fruit); 
         break; 
        default: 
         otherFruits.add(fruit); 
         break; 
       } 
    }); 

    genericFruitList.addAll(0, orangeList); 
    genericFruitList.addAll(1, applesList); 
    genericFruitList.addAll(2, watermelonList); 
    genericFruitList.addAll(3, otherFruits); 

Je me demande s'il y a un changement pour obtenir ce flux en utilisant la méthode triés et en utilisant un comparateur personnalisé ou quelque chose comme ça.

Merci d'avance.

+4

'Collectors.groupingBy (Fruit :: getName)' regrouperait les fruits par leur nom, comme dans le commutateur. Vous pourriez alors faire le 'addAll's comme ceci. –

+0

La création d'une classe d'aide peut vous donner la liste appropriée: fruitHelper.getList (fruit.getName) –

+3

Notez que votre logique actuelle est étrange. Disons que vous avez deux de chaque type de fruit: votre «genericFruitList» résultant serait «orange, pomme, pastèque, autre, autre, pastèque, pomme, orange». Voulez-vous spécifier le point d'insertion, ou avez-vous l'intention de tout ajouter à la fin? –

Répondre

6

Vous pouvez créer un comparateur en utilisant un ordre explicite comme

List<String> order = Arrays.asList("Orange", "Apple", "WaterMelon"); 
Comparator<String> comp 
    = Comparator.comparingInt(name -> order.indexOf(name)-Integer.MIN_VALUE); 

qui peut b e utilisé comme

List<Fruit> genericFruitList = fruits 
    .sorted(Comparator.comparing(fruit -> fruit.getName(), comp)) 
    .collect(Collectors.toList()); 

cependant, le tri de la liste complète, en particulier avec un comparateur à List.indexOf, peut être calme inefficace. Une alternative serait

List<Fruit> genericFruitList = fruits 
    .collect(Collectors.groupingBy(fruit -> fruit.getName())) 
    .entrySet().stream() 
    .sorted(Map.Entry.comparingByKey(comp)) 
    .flatMap(e -> e.getValue().stream()) 
    .collect(Collectors.toList()); 

qui effectue juste une recherche de hachage par Fruit et seulement trier les applications distinctes.

Cela peut être considéré comme une variante de Bucket Sort.

+0

Merci beaucoup. Cela a fonctionné parfaitement pour moi :) – Antonio682

5

Si vous voulez trier les fruits dans un ordre particulier (les oranges d'abord, puis les pommes, puis la pastèque, puis « autre »), vous pouvez définir un comparateur ainsi:

List<String> order = Arrays.asList("Orange", "Apple", "Watermelon"); 
Comparator<Fruit> comparator = Comparator.comparing(f -> { 
    int i = order.indexOf(f.getName()); 
    return (i >= 0) ? i : order.size(); 
}); 

puis tri:

List<Fruit> genericFruitList = fruits.stream().sorted(comparator).collect(Collectors.toList()); 
+0

btw gava a 'Ordering.explicit (Liste )' qui pourrait être utilisé ici aussi. – Eugene

+1

@Eugene ["Si vous utilisez Java 8, cette classe est désormais obsolète"] (https://google.github.io/guava/releases/23.0/api/docs/com/google/common/collect/Ordering. html). De plus, cela ne gère pas les "autres" valeurs. –