57 votes

Comprendre profondément les caractéristiques du spliterator

Afin d'essayer de comprendre en profondeur java ruisseaux et spliterators, j'ai quelques petites questions à propos de spliterator caractéristiques:

Q1: Stream.empty() vs Stream.of() (Ruisseau.de() sans arguments)

  • Stream.empty(): SUBSIZED, DE LA TAILLE D'
  • Stream.of(): SUBSIZED, IMMUABLE, DE TAILLE MOYENNE, A ORDONNÉ

Pourquoi Stream.empty() n'ont pas les mêmes caractéristiques de l' Stream.of()? Remarque qu'elle a des répercussions lors de l'utilisation en conjonction avec Stream.concat() (spécialement de ne pas avoir ORDERED). Je dirais qu' Stream.empty() devraient avoir non seulement IMMUABLE et ORDONNÉ , mais aussi DISTINCTES et NON nulles. Aussi il judicieux Stream.of() avec un seul argument avoir DISTRICT.

Q2: est - LongStream.of() n'ayant pas NON null

Viens de remarquer que le NON n'est pas disponible en LongStream.of. N'est-ce pas NONNULL l'une des principales caractéristiques de tous les LongStreams, IntStreams et DoubleStreams?

Q3: est - LongStream.range(,) vs LongStream.range(,).boxed()

  • LongRange.range(,): SUBSIZED, IMMUABLE, NON, DE TAILLE MOYENNE, D'ORDRE, DE LES TRIER, DISTINCTES
  • LongStream.range(,).boxed(): SUBSIZED, DE TAILLE MOYENNE, A ORDONNÉ

Pourquoi .boxed() perd toutes ces caractéristiques? Il ne faut pas perdre toute.

Je comprends qu' .mapToObj() peuvent perdre de la valeur NON null, IMMUABLE et de DISTRICT, mais .boxed()... ne fait pas de sens.

Q4: .peek() perd IMMUABLE et NON null

LongStream.of(1): SUBSIZED, IMMUABLE, NON, DE TAILLE MOYENNE, ... LongStream.of(1).peek(): SUBSIZED, DE TAILLE MOYENNE, ...

Pourquoi .peek() perd ces caractéristiques? .peek ne devrait pas vraiment perdre du tout.

Q5: .skip(), .limit() perd SUBSIZED, IMMUABLE, NON, de la TAILLE d'

Il suffit de remarquer que ces opérations perd SUBSIZED, IMMUABLE, NON, de TAILLE moyenne. Pourquoi? Si la taille est disponible, il est alors facile de calculer la taille finale ainsi.

Q6: est - .filter() perd IMMUABLE, NON

Il suffit de remarquer que ces opérations perd ainsi SUBSIZED, IMMUABLE, NON, de TAILLE moyenne. Il judicieux de perdre SUBSIZED et de TAILLE moyenne, mais les deux autres ne fait pas de sens. Pourquoi?


Je vais apprécier si quelqu'un qui comprend en profondeur de la spliterator pourrait apporter un peu de clarté. Merci.

37voto

Holger Points 13789

Je dois admettre que j'ai eu des difficultés aussi, quand j'ai d'abord essayé de trouver la signification réelle des caractéristiques et des eu le sentiment que leur sens n'est pas clairement établie lors de la phase de mise en œuvre de Java 8 et est utilisé de façon uniforme pour cette raison.

Envisager Spliterator.IMMUTABLE:

Valeur de caractéristique signifiant que l'élément source ne peut pas être modifié structurellement, c'est, les éléments ne peuvent pas être ajoutés, remplacés ou supprimés, de sorte que de tels changements ne peuvent se produire au cours de la traversée.

C'est étrange de voir "remplacé" dans cette liste, qui n'est généralement pas considéré comme une modification structurelle lorsqu'on parle d'un List ou un tableau et, par conséquent, de flux et de spliterator usines d'accepter un tableau (qui n'est pas cloné) rapport IMMUTABLE, comme LongStream.of(…) ou Arrays.spliterator(long[]).

Si nous interprétons ce plus généreusement que "aussi longtemps que pas observable par le client", il n'y a pas de différence significative d' CONCURRENT, comme dans les deux cas, certains éléments seront signalées au client sans aucun moyen pour reconnaître qu'elles ont été ajoutées au cours de la traversée, ou si certains ont été signalés en raison de l'enlèvement, comme il n'existe aucun moyen pour rembobiner un spliterator et de les comparer.

La spécification continue:

Un Spliterator qui n'a pas de rapport IMMUTABLE ou CONCURRENT devrait avoir une politique documentée (par exemple jeter ConcurrentModificationException) concernant structurels de l'interférence détectée au cours de la traversée.

Et c'est la seule chose, un spliterator de déclaration, soit, IMMUTABLE ou CONCURRENT, c'est la garantie de ne jamais jeter un ConcurrentModificationException. Bien sûr, CONCURRENT s ' oppose SIZED de la sémantique, mais qui n'a pas de conséquence pour le code client.

En fait, ces caractéristiques ne sont pas utilisés pour quoi que ce soit dans le Flux de l'API, par conséquent, de les utiliser de façon incohérente serait jamais remarqué quelque part.

C'est aussi l'explication de tous les intermédiaires en opération a pour effet de compensation de l' CONCURRENT, IMMUTABLE et NONNULL caractéristiques: le Ruisseau de la mise en œuvre n'a pas les utiliser et de ses classes internes représentant le flux de l'etat de ne pas les maintenir.


De même, NONNULL n'est pas utilisé n'importe où, donc, c'est l'absence de certains cours d'eau n'a aucun effet. Je pourrait suivre l' LongStream.of(…) question à l'usage interne de l' Arrays.spliterator(long[], int, int) qui délègue à
Spliterators.spliterator​(long[] array, int fromIndex, int toIndex, int additionalCharacteristics):

Le retour de l'spliterator signale toujours les caractéristiques SIZED et SUBSIZED. L'appelant peut fournir d'autres caractéristiques de la spliterator de rapport. (Par exemple, si elle est connue, le tableau ne sera pas modifié, spécifiez IMMUTABLE; si le tableau de données est considéré comme une rencontre de la commande, indiquez ORDERED). La méthode Arrays.spliterator(long[], int, int) peut souvent être utilisé à la place, qui renvoie un spliterator que les rapports d' SIZED, SUBSIZED, IMMUTABLE, et ORDERED.

Remarque (encore une fois) l'utilisation incohérente de l' IMMUTABLE caractéristique. Il est à nouveau traitée comme ayant à la garantie de l'absence de toute modification, alors que dans le même temps, Arrays.spliterator et, en retour, Arrays.stream et LongStream.of(…) fera rapport de l' IMMUTABLE caractéristique, même par la spécification, sans être en mesure de garantir que l'appelant de ne pas modifier leur tableau. Sauf si nous considérons la fixation d'un élément à ne pas être une modification structurelle, mais ensuite, l'ensemble de la distinction devient absurde encore une fois, que les tableaux ne peut pas être modifié structurellement.

Et il est clairement spécifié n' NONNULLcaractéristique. Alors qu'il est évident que les valeurs primitives ne peuvent pas être null, et l' Spliterator.Abstract<Primitive>Spliterator classes invariablement injecter un NONNULL caractéristique, le spliterator retourné par Spliterators.spliterator​(long[],int,int,int) n'hérite pas de Spliterator.AbstractLongSpliterator.

La mauvaise chose est, ce ne peut être résolu sans changer la spécification, la bonne chose est, il n'a pas de conséquences de toute façon.


Donc, si nous ignorons tout des problèmes avec CONCURRENT, IMMUTABLEou NONNULL, qui n'ont pas de conséquences, nous avons

SIZED et skip & limit. C'est une question bien connue, due à l' skip et limit ont été mis en œuvre par le Flux de l'API. D'autres implémentations sont imaginables. Cela s'applique également à la combinaison d'un courant infini avec un limit, ce qui devrait avoir un prévisible de la taille, mais compte tenu de la mise en œuvre actuelle, n'a pas.

Combinant Stream.concat(…) avec Stream.empty(). Il semble raisonnable qu'un vide de flux ne pas imposer des contraintes sur le résultat de la commande. Mais Stream.concat(…)s'comportement de relâcher la commande lors d'une seule entrée a pas d'ordre, est discutable. Notez que d'être trop agressif, concernant la commande n'est pas nouveau, voir ce Q&A concernant un comportement qui a été considérée comme intentionnelle d'abord, mais ensuite, il a été fixé comme la fin de Java 8, mise à jour 60. Peut-être, Stream.concat doit avoir été discuté à droite à ce point de temps aussi...

Le comportement de l' .boxed() est facile à expliquer. Quand il a été mis en œuvre naïvement comme .mapToObj(Long::valueOf), il va tout simplement perdre toutes les connaissances, mapToObj ne peut pas supposer que le résultat est toujours triés ou distinctes. Mais cela a été résolu avec Java 9. Il y a, LongStream.range(0,10).boxed() a SUBSIZED|SIZED|ORDERED|SORTED|DISTINCT caractéristiques, le maintien de toutes les caractéristiques qui ont une pertinence pour la mise en œuvre.

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