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' NONNULL
caracté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
, IMMUTABLE
ou 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.