Die in Java 8 hinzugefügte Iterator-Schnittstelle "Spliterator" kann abhängig von ihrer Datenquelle Eigenschaften beibehalten. Ich hatte das Gefühl, dass es Fälle gab, in denen es nicht offensichtlich war, welche Merkmale vorhanden sein sollten, und fasste daher die Werte von "Merkmalen" zusammen, die von "Spliterator" zurückgegeben wurden, der über die Standardbibliothek erstellt wurde.
java.util.Spliterator
ist eine neue Iterator-Schnittstelle, die in Java 8 hinzugefügt wurde.
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Spliterator.html
Apropos Java-Iteratoren: java.util.Iterator existiert seit der Antike. Der "Spliterator" ist ungefähr der gleiche wie dieser "Iterator", bietet jedoch eine optimierte API.
tryAdvance
Im Fall von "java.util.Iterator" werden die "hasNext" -Methode und die "next" -Methode kombiniert, um das Element zu iterieren. Das Protokoll besteht darin, "hasNext" zu verwenden, um zu überprüfen, ob das "nächste" Element vorhanden ist, und wenn ja, "next" zu verwenden, um dieses Element abzurufen.
Iterator<String> iterator = ……;
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Andererseits bietet "Spliterator" eine einzige Methode namens "tryAdvance", um das "nächste" Element zu erhalten.
tryAdvance
nimmt ein Element von Spliterator
und macht etwas Consumer Nimmt als Argument.
Wenn das "nächste" Element vorhanden ist, wird es von "Consumer" verdaut und gibt "true" zurück. Wenn das "nächste" Element nicht vorhanden ist, wird "Consumer" nicht ausgeführt und "false" wird zurückgegeben.
Spliterator<String> spliterator = ……;
do { } while (spliterator.tryAdvance(System.out::println));
trySplit
Der Schnittstellenname verbirgt auch seine Funktionalität, aber "Spliterator" bietet eine "trySplit" -Methode zum Teilen von Iteratoren. Dies ist eine API, die die Elemente des Empfänger-Spliterators in den Rückgabe-Spliterator aufteilt.
Normalerweise ist ein einzelner "Iterator" oder "Spliterator" nicht threadsicher. Jeder durch "trySplit" geteilte "Spliterator" kann jedoch von einem separaten Thread verarbeitet werden, sodass Elemente parallel durchlaufen werden können. Darüber hinaus ist "Spliterator" eine Schnittstelle, die sich der Parallel / Split-Governance sehr bewusst ist, z. B. die Möglichkeit, die Anzahl der Elemente zu erfassen und die später beschriebenen Merkmale anzugeben. StreamSupport verwendet dieses "trySplit" und diese Eigenschaften, um den Stream zu optimieren. Korrekt.
Wenn Sie beispielsweise "trySplit" von "Spliterator" aufrufen, das aus einem Array wie folgt erstellt wurde, wird jeder "Spliterator" so aufgeteilt, dass er für genau die Hälfte der Elemente verantwortlich ist.
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
kann Hinweise basierend auf seinen eigenen Eigenschaften speichern.
Derzeit können die Funktionen von "Spliterator" "CONCURRENT" und "DISTINCT" sein. "" [IMMUTABLE](https://docs.oracle.com/javase/ jp / 8 / docs / api / java / util / Spliterator.html # IMMUTABLE) "" [NICHT NULL](https://docs.oracle.com/javase/jp/8/docs/api/java/util/Spliterator. html # NONNULL) "" BESTELLT "" [GRÖSSE](https: // docs.oracle.com/javase/jp/8/docs/api/java/util/Spliterator.html#SIZED) "" [SORTIERT](https://docs.oracle.com/javase/jp/8/docs/ api / java / util / Spliterator.html # SORTED) "" SUBSIZED " Da sind acht.
Die Bedeutung ist dieselbe wie der konstante Name. Beispiel: "Spliterator" aus "Set" enthält garantiert keine doppelten Elemente, daher wird das Attribut "DISTINCT" hinzugefügt. "Spliterator" aus einem Array hat die Anzahl der Elemente. Da wir wissen, verwenden wir es beispielsweise zum Hinzufügen des Attributs "SIZED".
Ich war jedoch ein wenig besorgt über die Spezifikationen, da nicht klar war, ob das Attribut "DISTINCT" oder das Attribut "SORTED" hinzugefügt werden sollte, wenn klar war, dass es nur ein Element gab. Also habe ich beschlossen, "Spliterator" auf verschiedene Arten zu erstellen und die Beziehung zwischen der Datenstruktur und den Merkmalen zu sehen.
Da es ziemlich viele Umfragefälle gibt, habe ich die Ergebnisse in mehrere Muster unterteilt. Die Quelle von "Spliterator", die konkrete Klasse des erzeugten "Spliterators" und die Eigenschaften von "Spliterator" werden jeweils beschrieben.
Ich habe sie mit "Spliterators.spliterator" bzw. "Spliterators.spliteratorUnknownSize" erstellt. Es war das Ergebnis davon.
Quelle | Spliterator Betonklasse | Spliterator Eigenschaften |
---|---|---|
Mit Größenangabe | java.util.Spliterators$IteratorSpliterator | SIZED, SUBSIZED |
Keine Größe angegeben | java.util.Spliterators$IteratorSpliterator | Keiner |
Es sieht so aus, als würde es die Eigenschaften der Datenstruktur darstellen. Ich war jedoch besorgt, dass der Array-bezogene "Spliterator" nicht die "ORDERED" -Eigenschaft hat.
Quelle | Spliterator Betonklasse | Spliterator Eigenschaften |
---|---|---|
Array | 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 |
Fast alle Muster haben die Eigenschaft "IMMUTABLE" oder "CONCURRENT". Ich denke, der Grund, warum sie nicht in der PriorityBlockingQueue enthalten sind, liegt in der Datenstruktur des Heaps.
Quelle | Spliterator Betonklasse | Eigenschaften des Spliterators |
---|---|---|
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 |
Ich habe unveränderliche Singleton-Listen ausprobiert, die mit der Klasse "Sammlungen" erstellt wurden, unveränderliche Himmelslisten usw. Um ehrlich zu sein, bin ich der Meinung, dass die Eigenschaften der Immutable Sky Collection nicht ausreichen.
Quelle | Spliterator Betonklasse | Eigenschaften des Spliterators |
---|---|---|
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 |
Ich habe "Spliterator" auf verschiedene Arten erstellt und versucht, die Eigenschaften der einzelnen zu ermitteln. Obwohl ich die allgemeine Tendenz verstanden habe, scheint es, dass die Standardbibliothek selbst nicht unbedingt eine konsistente Implementierung ist.
Dies ist das Umfrageprotokoll. Da es lang ist, empfehlen wir Ihnen, sich auf die Ergebniszusammenfassung zu beziehen.
Java ist "Java HotSpot (TM) 64-Bit-Server-VM, Java 1.8.0_60".
Ich habe es mit Scala REPL versucht. Führen Sie die folgende Import- und Methodendefinition im Voraus durch.
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(", "))
}
Das zweite Argument von "Spliterators.spliterator" ist die Größe des Iterators, und das dritte Argument sind die zusätzlich angegebenen Merkmale. Wenn die Anwendungsebene beispielsweise garantiert, dass das Element nicht "null" ist, können Sie "NONNULL" als drittes Argument angeben. Wenn Sie 0 angeben, werden keine Merkmale hinzugefügt.
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
Der Iterator kann eine unbestimmte Anzahl von Elementen oder eine unendliche Anzahl von Elementen haben. Verwenden Sie in solchen Fällen "Spliterators.spliteratorUnknownSize", um "Spliterator" zu erstellen. Das zweite Argument sind die Merkmale, die Sie zusätzlich angeben
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)
Wenn Sie "Spliterator" so erstellen, wie es aus "Array [Int]" stammt, können Sie einen "Spliterator" erstellen, der auf primitive Arrays spezialisiert ist, sodass er in "AnyRef" (Java "Object" -Typ) umgewandelt wird.
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
Eine unveränderliche Liste mit nur einem Element.
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
Eine unveränderliche Menge mit nur einem Element.
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
Es ist eine unveränderliche Himmelsliste.
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
Es ist ein unveränderlicher Himmel.
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
Ein unveränderlicher Himmel 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
Leerer 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