Je lis Etat de Lambda: Libraries Edition , et je suis surpris par une affirmation:
Sous la section Streams , il y a ce qui suit:
List<Shape> blue = shapes.stream()
.filter(s -> s.getColor() == BLUE)
.collect(Collectors.toList());
Le document n'indique pas ce que shapes
est réellement, et je ne sais pas si cela compte vraiment.
Ce qui me trouble est la suivante: Quel type de béton List
ce bloc de code renvoie-t-il?
List<Shape>
, Ce qui est tout à fait correct.stream()
ni filter()
décide du type de liste à utiliser.Collectors.toList()
non plus ne spécifie le type concret de List
.Alors, quel type concret (sous-classe) de List
est utilisé ici? Y a-t-il des garanties?
Alors, quel type concret (sous-classe) de liste est utilisé ici? Y a-t-il des garanties?
Si vous consultez la documentation de Collectors#toList()
, il est indiqué que - "Il n’existe aucune garantie quant au type, à la mutabilité, à la sérialisabilité ou à la sécurité du fil de la liste. retourné ". Si vous souhaitez qu'une implémentation particulière soit renvoyée, vous pouvez utiliser Collectors#toCollection(Supplier)
.
Supplier<List<Shape>> supplier = () -> new LinkedList<Shape>();
List<Shape> blue = shapes.stream()
.filter(s -> s.getColor() == BLUE)
.collect(Collectors.toCollection(supplier));
Et à partir du lambda, vous pouvez renvoyer l’implémentation de List<Shape>
De votre choix.
Mise à jour :
Ou, vous pouvez même utiliser la référence de méthode:
List<Shape> blue = shapes.stream()
.filter(s -> s.getColor() == BLUE)
.collect(Collectors.toCollection(LinkedList::new));
En naviguant à travers Netbeans (Ctrl + Clic), j'ai atterri dans ce code. Il semble utiliser une ArrayList en tant que fournisseur.
public static <T> Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}