L'interface d'itérateur Spliterator
, ajoutée dans Java 8, peut conserver les caractéristiques de sa source de données.
J'ai senti qu'il y avait des cas où il n'était pas évident de savoir quelles caractéristiques devraient être possédées, j'ai donc résumé les valeurs des «caractéristiques» renvoyées par «Spliterator» créées via la bibliothèque standard.
java.util.Spliterator
est une nouvelle interface d'itérateur ajoutée dans Java 8.
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Spliterator.html
En parlant d'itérateurs Java, java.util.Iterator existe depuis l'Antiquité.
Spliterator
est à peu près le même que cet ʻIterator`, mais fournit une API plus optimisée.
tryAdvance
Dans le cas de java.util.Iterator
, la méthode hasNext
et la méthode next
sont combinées pour itérer l'élément.
Le protocole consiste à utiliser «hasNext» pour vérifier si l'élément «suivant» existe, et si c'est le cas, utilisez «suivant» pour obtenir cet élément.
Iterator<String> iterator = ……;
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
D'autre part, Spliterator
fournit une méthode unique appelée tryAdvance
pour obtenir l'élément" suivant ".
tryAdvance
prend un élément de Spliterator
et fait quelque chose Consumer Prend comme argument.
Si l'élément «suivant» existe, il sera digéré par «Consumer» et retournera «true». Si l'élément «next» n'existe pas, «Consumer» ne sera pas exécuté et «false» sera renvoyé.
Spliterator<String> spliterator = ……;
do { } while (spliterator.tryAdvance(System.out::println));
forEachRemaining
à la fois pour java.util.Iterator
et java.util.Spliterator
.trySplit
Le nom de l'interface cache également sa fonctionnalité, mais Spliterator
fournit une méthode trySplit
pour diviser les itérateurs.
Il s'agit d'une API qui divise les éléments du récepteur «Spliterator» dans le «Spliterator» de retour.
Habituellement, un seul «Itérateur» ou «Spliterator» n'est pas thread-safe.
Cependant, chaque Spliterator
divisé par trySplit
peut être traité par un thread séparé, ce qui permet de traverser des éléments en parallèle.
De plus, «Spliterator» est une interface qui est fortement consciente de la gouvernance parallèle / fractionnée, par exemple être capable d'acquérir le nombre d'éléments et de spécifier les caractéristiques décrites plus loin.
StreamSupport utilise ce «trySplit» et ses caractéristiques pour optimiser le flux. C'est vrai.
Par exemple, si vous appelez trySplit
de Spliterator
créé à partir d'un tableau comme suit, chaque Spliterator
sera divisé de sorte qu'il soit responsable d'exactement la moitié des éléments.
final int[] xs = {1, 2, 3, 4, 5, 6, 7, 8};
final Spliterator<Integer> a = Spliterators.spliterator(xs, 0);
final Spliterator<Integer> b = a.trySplit();
a.forEachRemaining(System.out::println); // 5, 6, 7, 8
b.forEachRemaining(System.out::println); // 1, 2, 3, 4
«Spliterator» peut stocker des indices en fonction de ses propres caractéristiques.
Actuellement, les fonctionnalités que Spliterator
peut avoir sont" CONCURRENT "et" DISTINCT. "" [IMMUTABLE](https://docs.oracle.com/javase/ jp / 8 / docs / api / java / util / Spliterator.html # IMMUTABLE) "" [NON NULL](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Spliterator. html # NONNULL) "" COMMANDÉ "" [SIZED](https: // docs.oracle.com/javase/jp/8/docs/api/java/util/Spliterator.html#SIZED) "" [TRIÉ](https://docs.oracle.com/javase/jp/8/docs/ api / java / util / Spliterator.html # SORTED) "" SUBSIZED " Il y en a huit.
La signification est la même que le nom de la constante, par exemple, Spliterator
fabriqué à partir de Set
est garanti sans éléments en double, donc l'attribut DISTINCT
est ajouté. Spliterator
fait à partir d'un tableau a le nombre d'éléments. Puisque nous le savons, nous l'utilisons comme l'ajout de l'attribut SIZED
.
Cependant, j'étais un peu inquiet au sujet des spécifications, car il n'était pas clair si l'attribut DISTINCT
ou l'attribut SORTED
devait être ajouté alors qu'il était clair qu'il n'y avait qu'un seul élément.
J'ai donc décidé de créer Spliterator
de différentes manières et de voir la relation entre la structure des données et les caractéristiques.
Comme il y a beaucoup de cas d'enquête, j'ai divisé les résultats en plusieurs modèles. La source de «Spliterator», la classe concrète générée de «Spliterator» et les caractéristiques de «Spliterator» sont décrites respectivement.
Je les ai créés avec Spliterators.spliterator
et Spliterators.spliteratorUnknownSize
, respectivement.
C'était le résultat de cela.
La source | Classe de béton Spliterator | Caractéristiques du séparateur |
---|---|---|
Avec spécification de taille | java.util.Spliterators$IteratorSpliterator | SIZED, SUBSIZED |
Aucune taille spécifiée | java.util.Spliterators$IteratorSpliterator | Aucun |
Il semble que les caractéristiques de la structure des données soient exprimées.
Cependant, je craignais que le Spliterator
issu d'un tableau n'ait la propriété ʻORDERED`.
La source | Classe de béton Spliterator | Caractéristiques du séparateur |
---|---|---|
Tableau | java.util.Spliterators$ArraySpliterator | SIZED, SUBSIZED |
ArrayList | java.util.ArrayList$ArrayListSpliterator | ORDERED, SIZED, SUBSIZED |
LinkedList | java.util.LinkedList$LLSpliterator | ORDERED, SIZED, SUBSIZED |
HashSet | java.util.HashMap$KeySpliterator | DISTINCT, SIZED |
LinkedHashSet | java.util.Spliterators$IteratorSpliterator | DISTINCT, ORDERED, SIZED, SUBSIZED |
TreeSet | java.util.TreeMap$KeySpliterator | DISTINCT, ORDERED, SIZED, SORTED |
PriorityQueue | java.util.PriorityQueue$PriorityQueueSpliterator | NONNULL, SIZED, SUBSIZED |
Presque tous les modèles ont la caractéristique «IMMUTABLE» ou «CONCURRENT».
Je pense que la raison pour laquelle ils ne sont pas dans la PriorityBlockingQueue
est due à la structure de données du tas.
La source | Classe de béton Spliterator | Caractéristiques du Spliterator |
---|---|---|
CopyOnWriteArrayList | java.util.Spliterators$ArraySpliterator | IMMUTABLE, ORDERED, SIZED, SUBSIZED |
CopyOnWriteArraySet | java.util.Spliterators$ArraySpliterator | DISTINCT, IMMUTABLE, SIZED, SUBSIZED |
ConcurrentSkipListSet | java.util.concurrent.ConcurrentSkipListMap$KeySpliterator | CONCURRENT, DISTINCT, NONNULL, ORDERED, SORTED |
ConcurrentLinkedQueue | java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator | CONCURRENT, NONNULL, ORDERED |
LinkedBlockingQueue | java.util.concurrent.LinkedBlockingQueue$LBQSpliterator | CONCURRENT, NONNULL, ORDERED |
LinkedTransferQueue | java.util.concurrent.LinkedTransferQueue$LTQSpliterator | CONCURRENT, NONNULL, ORDERED |
PriorityBlockingQueue | java.util.concurrent.PriorityBlockingQueue$PBQSpliterator | NONNULL, SIZED, SUBSIZED |
J'ai essayé des listes de singleton immuables créées à l'aide de la classe Collections
, des listes de ciel immuables, etc.
Pour être honnête, je pense que les caractéristiques de la collection Immutable Sky ne sont pas suffisantes.
La source | Classe de béton Spliterator | Caractéristiques du Spliterator |
---|---|---|
Collections.singletonList | java.util.Collections$2 | DISTINCT, IMMUTABLE, NONNULL, ORDERED, SIZED, SUBSIZED |
Collections.singleton | java.util.Collections$2 | DISTINCT, IMMUTABLE, NONNULL, ORDERED, SIZED, SUBSIZED |
Collections.emptyList | java.util.Spliterators$EmptySpliterator$OfRef | SIZED, SUBSIZED |
Collections.emptySet | java.util.Spliterators$EmptySpliterator$OfRef | SIZED, SUBSIZED |
Collections.emptySortedSet | java.util.TreeMap$KeySpliterator | DISTINCT, ORDERED, SIZED, SORTED |
Spliterators.emptySpliterator | java.util.Spliterators$EmptySpliterator$OfRef | SIZED, SUBSIZED |
J'ai créé Spliterator
de différentes manières et j'ai essayé d'obtenir les caractéristiques de chacun.
Bien que j'aie saisi la tendance générale, il semble que la bibliothèque standard elle-même ne soit pas nécessairement une implémentation cohérente.
Ceci est le journal d'enquête. Comme il est long, nous vous recommandons de vous référer au résumé des résultats.
Java est "Java HotSpot (TM) 64-Bit Server VM, Java 1.8.0_60".
Je l'ai essayé avec Scala REPL. Effectuez à l'avance l'importation suivante et la définition de méthode.
import java.util._
import java.util.concurrent._
def printCharacteristics[T](spliterator:Spliterator[T]): Unit = {
println(Seq(
if (spliterator.hasCharacteristics(Spliterator.CONCURRENT)) Some("CONCURRENT") else None,
if (spliterator.hasCharacteristics(Spliterator.DISTINCT)) Some("DISTINCT") else None,
if (spliterator.hasCharacteristics(Spliterator.IMMUTABLE)) Some("IMMUTABLE") else None,
if (spliterator.hasCharacteristics(Spliterator.NONNULL)) Some("NONNULL") else None,
if (spliterator.hasCharacteristics(Spliterator.ORDERED)) Some("ORDERED") else None,
if (spliterator.hasCharacteristics(Spliterator.SIZED)) Some("SIZED") else None,
if (spliterator.hasCharacteristics(Spliterator.SORTED)) Some("SORTED") else None,
if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) Some("SUBSIZED") else None
).flatten.mkString(", "))
}
Le deuxième argument de Spliterators.spliterator
est la taille de l'itérateur, et le troisième argument est les caractéristiques spécifiées en plus.
Par exemple, si le niveau application garantit que l'élément n'est pas «nul», vous pouvez spécifier «NONNULL» comme troisième argument.
Spécifier 0 n'ajoute aucune caractéristique.
scala> val iterator = new java.util.Iterator[Int] {
| var i = 0
| def hasNext(): Boolean = i < 8
| def next(): Int = {
| if (i >= 8) throw new NoSuchElementException()
| i += 1
| i
| }
| }
iterator: java.util.Iterator[Int]{def i: Int; def i_=(x$1: Int): Unit} = $anon$1@1d6dc2b8
scala> val spliterator = Spliterators.spliterator(iterator, 8, 0)
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$IteratorSpliterator@5c8e7687
scala> printCharacteristics(spliterator)
SIZED, SUBSIZED
L'itérateur peut avoir un nombre indéterminé d'éléments ou un nombre infini d'éléments.
Dans de tels cas, utilisez Spliterators.spliteratorUnknownSize
pour créer Spliterator
.
Le deuxième argument est les caractéristiques que vous spécifiez en plus
scala> val iterator = new java.util.Iterator[Int] {
| var i = 0
| def hasNext(): Boolean = i < 8
| def next(): Int = {
| if (i >= 8) throw new NoSuchElementException()
| i += 1
| i
| }
| }
iterator: java.util.Iterator[Int]{def i: Int; def i_=(x$1: Int): Unit} = $anon$1@1c96bf1e
scala> val spliterator = Spliterators.spliteratorUnknownSize(iterator, 0)
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$IteratorSpliterator@44ba9f25
scala> printCharacteristics(spliterator)
Si vous créez Spliterator
tel qu'il est à partir de ʻArray [Int], vous pouvez créer
Spliterator spécialisé pour les tableaux primitifs, donc je l'ai converti en ʻAnyRef
(type Java ʻObject`).
scala> val spliterator = Spliterators.spliterator[Int]((1to8).toArray.map(_.asInstanceOf[AnyRef]),0)
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$ArraySpliterator@32ca397b
scala> printCharacteristics(spliterator)
SIZED, SUBSIZED
ArrayList
scala> val collection = new ArrayList[Int]()
collection: java.util.ArrayList[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.ArrayList$ArrayListSpliterator@7d3af2f0
scala> printCharacteristics(spliterator)
ORDERED, SIZED, SUBSIZED
LinkedList
scala> val collection = new LinkedList[Int]()
collection: java.util.LinkedList[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.LinkedList$LLSpliterator@71637a85
scala> printCharacteristics(spliterator)
ORDERED, SIZED, SUBSIZED
HashSet
scala> val collection = new HashSet[Int]()
collection: java.util.HashSet[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.HashMap$KeySpliterator@71daf5d6
scala> printCharacteristics(spliterator)
DISTINCT, SIZED
LinkedHashSet
scala> val collection = new LinkedHashSet[Int]()
collection: java.util.LinkedHashSet[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$IteratorSpliterator@28391cc6
scala> printCharacteristics(spliterator)
DISTINCT, ORDERED, SIZED, SUBSIZED
TreeSet
scala> val collection = new TreeSet[Int]()
collection: java.util.TreeSet[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.TreeMap$KeySpliterator@62b630e0
scala> printCharacteristics(spliterator)
DISTINCT, ORDERED, SIZED, SORTED
PriorityQueue
scala> val collection = new PriorityQueue[Int]()
collection: java.util.PriorityQueue[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.PriorityQueue$PriorityQueueSpliterator@6f75d11b
scala> printCharacteristics(spliterator)
NONNULL, SIZED, SUBSIZED
CopyOnWriteArrayList
scala> val collection = new CopyOnWriteArrayList[Int]()
collection: java.util.concurrent.CopyOnWriteArrayList[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$ArraySpliterator@5a931c02
scala> printCharacteristics(spliterator)
IMMUTABLE, ORDERED, SIZED, SUBSIZED
CopyOnWriteArraySet
scala> val collection = new CopyOnWriteArraySet[Int]()
collection: java.util.concurrent.CopyOnWriteArraySet[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$ArraySpliterator@ca024d8
scala> printCharacteristics(spliterator)
DISTINCT, IMMUTABLE, SIZED, SUBSIZED
ConcurrentSkipListSet
scala> val collection = new ConcurrentSkipListSet[Int]()
collection: java.util.concurrent.ConcurrentSkipListSet[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.concurrent.ConcurrentSkipListMap$KeySpliterator@7e003cf0
scala> printCharacteristics(spliterator)
CONCURRENT, DISTINCT, NONNULL, ORDERED, SORTED
ConcurrentLinkedQueue
scala> val collection = new ConcurrentLinkedQueue[Int]()
collection: java.util.concurrent.ConcurrentLinkedQueue[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.concurrent.ConcurrentLinkedQueue$CLQSpliterator@ffbdb79
scala> printCharacteristics(spliterator)
CONCURRENT, NONNULL, ORDERED
LinkedBlockingQueue
scala> val collection = new LinkedBlockingQueue[Int]()
collection: java.util.concurrent.LinkedBlockingQueue[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.concurrent.LinkedBlockingQueue$LBQSpliterator@d57ba2a
scala> printCharacteristics(spliterator)
CONCURRENT, NONNULL, ORDERED
LinkedTransferQueue
scala> val collection = new LinkedTransferQueue[Int]()
collection: java.util.concurrent.LinkedTransferQueue[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.concurrent.LinkedTransferQueue$LTQSpliterator@2977084e
scala> printCharacteristics(spliterator)
CONCURRENT, NONNULL, ORDERED
PriorityBlockingQueue
scala> val collection = new PriorityBlockingQueue[Int]()
collection: java.util.concurrent.PriorityBlockingQueue[Int] = []
scala> (1 to 8).foreach(collection.add)
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.concurrent.PriorityBlockingQueue$PBQSpliterator@1fd97710
scala> printCharacteristics(spliterator)
NONNULL, SIZED, SUBSIZED
Collections.singletonList
Une liste immuable avec un seul élément.
scala> val collection = Collections.singletonList(1)
collection: java.util.List[Int] = [1]
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Collections$2@56625ce9
scala> printCharacteristics(spliterator)
DISTINCT, IMMUTABLE, NONNULL, ORDERED, SIZED, SUBSIZED
Collections.singlton
Un ensemble immuable avec un seul élément.
scala> val collection = Collections.singleton(1)
collection: java.util.Set[Int] = [1]
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Collections$2@60d501f6
scala> printCharacteristics(spliterator)
DISTINCT, IMMUTABLE, NONNULL, ORDERED, SIZED, SUBSIZED
Collections.emptyList
C'est une liste de ciel immuable.
scala> val collection = Collections.emptyList[Int]()
collection: java.util.List[Int] = []
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$EmptySpliterator$OfRef@170f6972
scala> printCharacteristics(spliterator)
SIZED, SUBSIZED
Collections.emptySet
C'est un ciel immuable.
scala> val collection = Collections.emptySet[Int]()
collection: java.util.Set[Int] = []
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$EmptySpliterator$OfRef@170f6972
scala> printCharacteristics(spliterator)
SIZED, SUBSIZED
Collections.emptySortedSet
Un ciel immuable SortedSet.
scala> val collection = Collections.emptySortedSet[Int]()
collection: java.util.SortedSet[Int] = []
scala> val spliterator = collection.spliterator()
spliterator: java.util.Spliterator[Int] = java.util.TreeMap$KeySpliterator@d5ce7bb
scala> printCharacteristics(spliterator)
DISTINCT, ORDERED, SIZED, SORTED
Spliterators.emptySpliterator
Videz le Spliterator
.
scala> val spliterator = Spliterators.emptySpliterator[Int]()
spliterator: java.util.Spliterator[Int] = java.util.Spliterators$EmptySpliterator$OfRef@170f6972
scala> printCharacteristics(spliterator)
SIZED, SUBSIZED
Recommended Posts