Pile à l'aide de l'API de streaming de la collection Java 8


J'ai une méthode qui génère un objet chaque fois que je l'exécute, et je dois inverser l'ordre avec lequel je les obtiens. J'ai donc pensé que la façon naturelle de le faire serait une pile, car c'est LIFO.

Cependant, la pile Java ne semble pas bien fonctionner avec la nouvelle API de streaming Java 8.

Si je fais ceci:

   Stack<String> stack = new Stack<String>();
   stack.push("A");
   stack.push("B");
   stack.push("C");

   List<String> list = stack.stream().collect(Collectors.toList());
   System.out.println("Collected: " + list);

La sortie que j'obtiens est:

Collected: [A, B, C]

Pourquoi ne les envoie - t-il pas dans l'ordre LIFO attendu au flux? Est-ce la bonne façon de videz tous les éléments de la pile dans une liste dans le bon ordre (LIFO)?

Author: Tagir Valeev, 2015-05-22

1 answers

, Comme déjà mentionné dans les commentaires, nous avons bien testé Deque l'interface qui doit être privilégié.

Mais je vais vous donner la raison pourquoi Stack ne devrait pas être utilisé.

Au début, le Doc Java. de la Pile se dit:

Un ensemble plus complet et cohérent d'opérations de pile LIFO est fourni par l'interface Deque et ses implémentations, qui devraient être utilisé de préférence à cette classe. Par exemple:

Deque pile = new ArrayDeque();

Voir JavaDoc.

Alors quel est le problème avec la classe Stack.

Comme Martin Fowler déjà mentionné dans son livre Refactoring: Amélioration de la conception du Code existant à la méthode de refactoringRemplacer l'héritage par la délégation , une pile ne doit pas hériter d'un vecteur.

L'un des exemples classiques d'héritage inapproprié est faire un pile une sous-classe de vecteur. Java 1.1 le fait dans ses utilitaires (vilains garçons!) [6, p. 288]

Au lieu de cela, ils auraient dû utiliser la délégation comme dans l'image ci-dessous, qui est aussi dans le livre.

Voir aussi ici: Remplacer l'Héritage avec la Délégation

Remplacer l'héritage par la délégation

Donc, mais pourquoi est-ce un problème:

Parce que la pile n'a que 5 Méthodes:

  1. pop
  2. pousser
  3. isEmpty
  4. recherche
  5. Taille

    size() et isEmpty() sont héritées de l'Vector la classe et les autres méthodes de la Vector ne sont pas utilisés. Mais grâce à l'héritage, d'autres méthodes sont transmises à la classe Stack, ce qui n'a aucun sens.

Et Fowler dit à ce problème:

Vous pouvez vivre avec la situation et utiliser la convention pour dire que bien qu'il s'agisse d'une sous-classe, il n'utilise qu'une partie de la superclasse fonction. Mais cela se traduit par un code qui dit une chose lorsque votre l'intention est autre chose-une confusion que vous devriez supprimer.

Cela nuit au principe de ségrégation d'interface

, Qui dit:

LES CLIENTS NE DEVRAIENT PAS ÊTRE OBLIGÉS DE DÉPENDRE DES INTERFACES QU'ILS FONT NE PAS UTILISER.


Vous pouvez consulter le code source de la Vecteur et Pile classe et vous verrez que la classe Stack hérite de la méthode spliterator et le VectorSpliterator innerClass de la classe Vector.

Cette méthode est utilisée par l'interface Collection pour impl. la version par défaut de la méthode stream:

default Stream<E> More ...stream() {
  return StreamSupport.stream(spliterator(), false);
}

Évitez donc simplement l'utilisation de la classe Vector et Stack.

[6] Refactoring: Amélioration de la conception du code existant Fowler, Martin année 1997

 24
Author: Zelldon, 2018-01-27 16:50:24