46 votes

Est-il permis / conseillé de réutiliser un collecteur?

J'ai beaucoup de taches dans mon code qui ne:

someStream.collect(Collectors.toList())

Collectors.toList() crée un nouveau collecteur à chaque utilisation.

Cela m'amène à la question de savoir s'il est permis et même recommandé de faire quelque chose comme:

private final static Collector<…> TO_LIST = Collectors.toList()

pour chaque type d'-je utiliser et faire usage de ce Collectionneur comme:

someStream.collect(TO_LIST)

lorsqu'un agent est nécessaire.

Les collectionneurs sont des apatrides, et seulement une collection de fonctions et de caractéristiques, je pense que cela devrait fonctionner, mais otoh, que, Collectors.toList() crée un nouveau CollectorImpl<> sur tous les appels.

Quels sont les inconvénients de la réutilisation d'un Collectionneur?

35voto

GhostCat Points 83269

Je pense que c'est plus un style de question, mais permet de donner quelques idées:

  • Il semble être commun pratique pour ne pas utiliser un tel CONST objet collector. En ce sens: cela pourrait en surprendre certains lecteurs, et de surprendre les lecteurs est rarement une bonne chose à faire.
  • Alors: peu de code peut être simplement "copié" autour de (et ne devrait probablement pas à éviter la duplication de code); mais encore: pointant vers un distinct objet collector pourrait le rendre un peu plus difficile pour vous de re-facteur ou de ré-utiliser votre flux de constructions.
  • Au-delà: vous l'avez dit vous-même; de collecteur de ré-utilisation repose sur l'un des apatrides mise en œuvre. Donc, vous faites vous-même dépend de la mise en œuvre apatrides. Probablement pas un problème; mais peut-être un risque à garder à l'esprit!
  • Probablement le plus important: sur la surface, votre idée ressemble à une belle moyenne pour l'optimisation. Mais bien; quand vous vous inquiétez au sujet de la "performance" effets de l'utilisation de flux, alors qu'un seul objet de la création de la finale collector "couper"!

Ce que je veux dire: si vous êtes inquiet de "gaspiller" de la performance; vous préférez regarder dans chaque ligne de code qui utilise les flux de déterminer si le flux est de travailler avec "assez" objets à justifier l'utilisation des cours d'eau dans la première place. Ces flux de venir avec assez peu de frais généraux!

Longue histoire courte: la communauté de java a encore à trouver des "meilleures pratiques" pour les cours d'eau; ainsi, ma (personnelle) à deux cent à ce moment: préférer ces motifs que "tout le monde" est l'aide - évitez de faire votre propre chose. Surtout quand il est "lié à la performance".

30voto

Holger Points 13789

Depuis l' Collector est en fait un conteneur pour les quatre fonctions et les caractéristiques des drapeaux, il n'y a pas de problème de le réutiliser, mais aussi rarement un avantage, comme l'impact d'un tel objet léger sur la gestion de la mémoire est négligeable, si pas complètement supprimées par l'optimiseur de toute façon.

La principale raison de ne pas réutiliser Collectors, comme on le voit avec le groupe builtin Collectors, est, que vous ne pouvez pas le faire dans un type de façon sécuritaire. Lorsqu'on propose un collecteur pour arbitrairement tapé Lists, vous aurez besoin décoché opérations à toujours le même Collector de l'instance. Si vous stockez un Collector correctement tapé variable au lieu de cela, pour être utilisé sans décoché des opérations, vous pouvez l'utiliser seulement pour un type d' Lists, de rester avec cet exemple.

Dans le cas d' Collections.emptyList(), etc., le JRE développeurs a une façon différente, mais les constantes EMPTY_LIST, EMPTY_MAP, EMPTY_SET existaient déjà avant l'introduction de médicaments Génériques, et je dirais qu'ils sont plus polyvalents que les quelques cachable Collectors, qui sont seulement quatre cas particuliers de l'autre de plus de trente builtin collectionneurs, qui ne peuvent pas être mis en cache, en raison de leurs paramètres de la fonction. Depuis les paramètres de la fonction sont souvent mises en œuvre par les expressions lambda, qui génèrent des objets d'une quelconque identité/égalité, un cache de cartographie à collecteur cas aurait imprévisible de l'efficacité, mais très probablement beaucoup moins efficace que le gestionnaire de mémoire traitera de la des instances temporaires.

13voto

Honza Zidek Points 1571

C'est une bonne pratique pour une bibliothèque pour fournir une méthode de fabrique pour l'obtention d'objets utiles. La bibliothèque a fourni une telle méthode: Collectors.toList(), c'est à nouveau une bonne pratique de laisser la bibliothèque de décider s'il convient de créer une nouvelle instance à chaque fois que l'objet est demandé ou non, à la place de l'altération de la bibliothèque, ce qui diminue la lisibilité et de la mettre en danger l'avenir des problèmes lors de la mise en œuvre des changements.

Cet être ajouté à la GhostCat et Holger réponse comme un soutien argument :)

6voto

Eugene Points 6271

Juste une petite note, ce que @Holger dit dans sa réponse sur l'optimisation intelligente et le remplacement intégral de cette construction est tout à fait faisable et s'appelle scalar replacement . Lorsqu'un objet utilisé dans une méthode est déconstruit et que ses champs sont stack allocated like normal local variables . Ainsi, les Collector résultants pourraient ne pas être traités au niveau de la JVM en tant qu'objet en soi. Cela se produirait à JIT time .

3voto

OldCurmudgeon Points 16615

Le problème classique de l'utilisation d'un seul objet statique pour remplacer celui créé à la volée est la mutabilité. Une analyse rapide de la source Java 8 met en évidence le champ Set<Characteristics> comme un problème possible.

Clairement, il serait possible pour un code quelque part de faire quelque chose comme:

 private final static Collector<Object, ?, List<Object>> TO_LIST = Collectors.toList();


public void test() {
    // Any method could do this (no idea why but it should be possible).
    TO_LIST.characteristics().add(Collector.Characteristics.IDENTITY_FINISH);
}
 

Cela pourrait changer globalement la fonctionnalité de chaque utilisation de TO_LIST ce qui pourrait créer des bogues très obscurs.

Alors à mon humble avis - ne le faites pas!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X