Il semble que Stalin Sort soit populaire, je vais donc l'écrire en Java. L'API de flux introduite à partir de Java 8 est déjà familière, n'est-ce pas? Cette fois, nous allons créer une classe d'implémentation de l'interface Collector que la méthode Collect reçoit afin que le flux puisse effectuer un tri en sterling cool.
/**
*Classe d'implémentation de collecteur qui implémente le tri Staline
*/
public final class StalinSortCollector {
private StalinSortCollector() {}
/**
*Renvoie un Collector qui Starlin trie les éléments d'entrée dans l'ordre naturel et convertit le résultat en Stream.
* @param <T>Type d'élément d'entrée
*/
public static <T extends Comparable<? super T>> Collector<T, List<T>, Stream<T>> sorting(){
return new StalinSortCollectorImplements<T, T>(Comparator.naturalOrder(), x -> x);
}
/**
*Renvoie un Collector qui Starlin trie les éléments d'entrée dans l'ordre naturel inverse et convertit le résultat en Stream.
* @param <T>Type d'élément d'entrée
*/
public static <T extends Comparable<? super T>> Collector<T, List<T>, Stream<T>> reverseSorting(){
return new StalinSortCollectorImplements<T, T>(Comparator.reverseOrder(), x -> x);
}
/**
*Renvoie un Collector qui Staline trie les éléments d'entrée dans l'ordre naturel des valeurs converties par la fonction mappeur et convertit le résultat en Stream.
* @param mapper Fonction pour convertir les éléments d'entrée
* @param <T>Type d'élément d'entrée
* @param <A>Tapez pour comparer les éléments d'entrée
*/
public static <T, A extends Comparable<? super A>> Collector<T, List<T>, Stream<T>> sortingBy(Function<? super T, ? extends A> mapper){
return new StalinSortCollectorImplements<T, A>(Comparator.naturalOrder(), mapper);
}
/**
*Renvoie un collecteur qui Staline trie les éléments d'entrée dans l'ordre inverse de l'ordre naturel des valeurs converties par la fonction de mappage et convertit le résultat en Stream.
* @param mapper Fonction pour convertir les éléments d'entrée
* @param <T>Type d'élément d'entrée
* @param <A>Tapez pour comparer les éléments d'entrée
*/
public static <T, A extends Comparable<? super A>> Collector<T, List<T>, Stream<T>> reverseSortingBy(Function<? super T, ? extends A> mapper){
return new StalinSortCollectorImplements<T, A>(Comparator.reverseOrder(), mapper);
}
/**
*Renvoie un Collector qui Starlin trie les éléments d'entrée dans l'ordre dans lequel ils sont comparés par le comparateur et convertit le résultat en Stream.
* @Comparateur pour comparer les éléments du comparateur de paramètres
* @param <T>Type d'élément d'entrée
*/
public static <T> Collector<T, List<T>, Stream<T>> sorting(Comparator<? super T> comparator){
return new StalinSortCollectorImplements<T, T>(comparator, x -> x);
}
/**
*Renvoie un Collector qui Staline trie les éléments d'entrée convertis par la fonction de mappage dans l'ordre dans lequel ils sont comparés par le comparateur et convertit le résultat en Stream.
* @param mapper Fonction pour convertir les éléments d'entrée
* @Comparateur pour comparer les éléments du comparateur de paramètres
* @param <T>Type d'élément d'entrée
* @param <A>Tapez pour comparer les éléments d'entrée
*/
public static <T, A> Collector<T, List<T>, Stream<T>> sortingBy(Function<? super T, ? extends A> mapper, Comparator<? super A> comparator){
return new StalinSortCollectorImplements<T, A>(comparator, mapper);
}
private static class StalinSortCollectorImplements<T, A> implements Collector<T, List<T>, Stream<T>> {
private final Comparator<? super A> comparator;
private final Function<? super T, ? extends A> mapper;
private StalinSortCollectorImplements(Comparator<? super A> comparator, Function<? super T, ? extends A> mapper) {
this.comparator = comparator;
this.mapper = mapper;
}
@Override
public Supplier<List<T>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<T>, T> accumulator() {
return (list, element) -> {
if(list.isEmpty() || this.comparator.compare(this.mapper.apply(element), this.mapper.apply(list.get(list.size() -1))) >= 0) {
list.add(element);
}
};
}
@Override
public BinaryOperator<List<T>> combiner() {
return (x, y) -> Stream.concat(x.stream(), y.stream().dropWhile(p -> this.comparator.compare(this.mapper.apply(p), this.mapper.apply(x.get(x.size() -1))) < 0)).collect(Collectors.toList());
}
@Override
public Function<List<T>, Stream<T>> finisher() {
return List::stream;
}
@Override
public Set<Characteristics> characteristics() {
return EnumSet.of(Characteristics.CONCURRENT);
}
}
}
Collectors En référence à la classe, StalinSortCollector n'a que des méthodes statiques qui renvoient des Collectors. Je te laisse. La classe StalinSortCollectorImplements implémente en fait Stalin Sort.
Collector L'interface indique la méthode de collecte en la passant à la méthode de collecte de Stream. .. Il a 3 paramètres de type, 5 méthodes et 2 méthodes staiques (non pertinent car non implémenté).
Par exemple, s'il s'agit d'un collecteur qui ajoute une collection d'entiers à StringBuilder et le renvoie finalement sous forme de chaîne, ce sera \ <Integer, StringBuilder, String>.
Cette fois, StalinSortCollectorImplements ajoute un élément de type T à List \
Supplier<A> supplier()
Voici une description des méthodes à mettre en œuvre.
Le fournisseur renvoie un fournisseur qui crée une instance qui accumule les résultats en cours de route.
En parlant de l'instruction for, c'est ce que vous voulez faire avec for ([here] ;;)
(formule d'initialisation de for).
De plus, puisque le résultat intermédiaire réutilise l'instance générée par this, il n'est pas possible de renvoyer une chaîne de caractères vide et de faire quelque chose comme la concaténation de chaînes. (Parce que la combinaison de chaînes renvoie une nouvelle instance)
Ici, il renvoie ArrayList :: new.
BiConsumer<A, T> accumulator()
L'accumulateur prend un élément d'entrée de type T et renvoie un BiConsumer qui accumule les résultats intermédiaires dans une instance de type A.
En parlant de déclarations for, c'est ce que vous voulez faire avec for (;;) [here]
(le corps de for).
Ici, il est ajouté à la liste lorsque la liste qui stocke les résultats intermédiaires est vide ou lorsque "élément d'entrée> = dernier élément de la liste". (Inversement, lorsque "élément d'entrée <dernier élément de la liste", ** silence ** est terminé.)
BinaryOperator<A> combiner()
combiner renvoie un BinaryOperator qui combine des instances de type A qui ont accumulé des résultats intermédiaires. Puisque Stream peut être exécuté en parallèle, il est nécessaire de concaténer les résultats produits lorsqu'ils sont exécutés en parallèle avec cette fonction de combinateur. Ici, les éléments de la liste du côté concaténé sont ignorés (** nettoyés) jusqu'à ce qu'ils soient égaux ou supérieurs au dernier élément du côté concaténé. Notez que dropWhile ne peut être utilisé qu'avec Java 9 ou version ultérieure.
Function<A, R> finisher()
finisher renvoie la fonction du processus de finition pour l'instance de type A qui a accumulé tous les résultats. Ici, la liste triée par Starlin est renvoyée sous forme de flux. Cela permet à collect de continuer la chaîne de méthodes même s'il s'agit d'une opération de terminaison.
Set
caractéristiques renvoie un ensemble de caractéristiques de collecteur qui indique les attributs de ce collecteur. Il existe trois types: CONCURRENT (peut être exécuté en parallèle), UNORDERED (pas d'ordre) et IDENTITY_FINISH (le module de finition peut être omis). Ici, seul CONCURRENT est renvoyé car le finisseur est en cours de traitement et la commande est un tri important.
public class Soviet {
public static void main(String... args) {
Stream.of(1,2,2,4,3,5,3,5,7,1,1,9)
.collect(StalinSortCollector.sorting())
.forEach(System.out::println);
}
}
1
2
2
4
5
5
7
9
public class Russia {
public static void main(String... args) {
Stream.of(12,2,23,499,325,51,334,55555,7898,1019,19,12345)
.parallel()
.collect(StalinSortCollector.sortingBy(x -> String.valueOf(x).length()))
.forEach(System.out::println);
}
}
12
23
499
325
334
55555
12345
Après tout, ça fait du bien de pouvoir traiter avec stream.
Recommended Posts