Stream接口實現了 BaseStream 接口,咱們先來看看BaseStream的定義html
BaseStream是全部流的父類接口。java
/** * Base interface for streams, which are sequences of elements supporting * sequential and parallel aggregate operations. The following example * illustrates an aggregate operation using the stream types {@link Stream} * and {@link IntStream}, computing the sum of the weights of the red widgets: * * <pre>{@code * int sum = widgets.stream() * .filter(w -> w.getColor() == RED) * .mapToInt(w -> w.getWeight()) * .sum(); * }</pre> * * See the class documentation for {@link Stream} and the package documentation * for <a href="package-summary.html">java.util.stream</a> for additional * specification of streams, stream operations, stream pipelines, and * parallelism, which governs the behavior of all stream types. * * @param <T> the type of the stream elements * @param <S> the type of of the stream implementing {@code BaseStream} S 表明中間操做產生的新的流操做。 * @since 1.8 * @see Stream * @see IntStream * @see LongStream * @see DoubleStream * @see <a href="package-summary.html">java.util.stream</a> */ public interface BaseStream<T, S extends BaseStream<T, S>> extends AutoCloseable { /** * Returns an iterator for the elements of this stream. * * <p>This is a <a href="package-summary.html#StreamOps">terminal * operation</a>. * * @return the element iterator for this stream */ Iterator<T> iterator(); //迭代器 ,針對於流中元素類型*(T)的迭代器 /** * Returns a spliterator for the elements of this stream. * * <p>This is a <a href="package-summary.html#StreamOps">terminal * operation</a>. * * @return the element spliterator for this stream */ Spliterator<T> spliterator(); //分割迭代器, 流中的核心的操做。 /** * Returns whether this stream, if a terminal operation were to be executed, * would execute in parallel. Calling this method after invoking an * terminal stream operation method may yield unpredictable results. * * @return {@code true} if this stream would execute in parallel if executed */ boolean isParallel(); //是否並行 /** * Returns an equivalent stream that is sequential. May return * itself, either because the stream was already sequential, or because * the underlying stream state was modified to be sequential.,. 返回一個等價的串行流,有可能返回流自己,或者是流修改爲串行流的 * * <p>This is an <a href="package-summary.html#StreamOps">intermediate * operation</a>. * * @return a sequential stream */ S sequential(); //返回值爲S:流,新的流對象 /** * Returns an equivalent stream that is parallel. May return * itself, either because the stream was already parallel, or because * the underlying stream state was modified to be parallel. * * <p>This is an <a href="package-summary.html#StreamOps">intermediate * operation</a>. * * @return a parallel stream */ S parallel(); /** * Returns an equivalent stream that is * <a href="package-summary.html#Ordering">unordered</a>. May return * itself, either because the stream was already unordered, or because * the underlying stream state was modified to be unordered. * * <p>This is an <a href="package-summary.html#StreamOps">intermediate * operation</a>. * * @return an unordered stream */ S unordered(); /** * Returns an equivalent stream with an additional close handler. Close * handlers are run when the {@link #close()} method * is called on the stream, and are executed in the order they were * added. All close handlers are run, even if earlier close handlers throw * exceptions. If any close handler throws an exception, the first * exception thrown will be relayed to the caller of {@code close()}, with * any remaining exceptions added to that exception as suppressed exceptions * (unless one of the remaining exceptions is the same exception as the * first exception, since an exception cannot suppress itself.) May * return itself. 返回值爲流。流中帶了一個關閉處理器、關閉處理器調用的是 close()方法。 按照被添加的順序去關閉。 * * <p>This is an <a href="package-summary.html#StreamOps">intermediate * operation</a>. * * @param closeHandler A task to execute when the stream is closed * @return a stream with a handler that is run if the stream is closed */ S onClose(Runnable closeHandler); /** * Closes this stream, causing all close handlers for this stream pipeline * to be called. * * @see AutoCloseable#close() */ @Override void close(); }
public class StreamTest2 { public static void main(String[] args) { List<String> list = Arrays.asList("hello", "world", "hello world"); // list.stream().onClose(()-> System.out.println("aaa")).onClose(()-> System.out.println("bbb")).forEach(System.out::println); try (Stream<String> stream = list.stream()){ stream.onClose(()-> { System.out.println("aaa"); throw new NullPointerException("first Exception"); }).onClose(()->{ System.out.println("bbb"); throw new ArithmeticException("first Exception"); }).forEach(System.out::println); } } }
Exception in thread "main" java.lang.NullPointerException: first Exception at com.dawa.jdk8.StreamTest2.lambda$main$0(StreamTest2.java:21) at java.util.stream.Streams$1.run(Streams.java:850) at java.util.stream.AbstractPipeline.close(AbstractPipeline.java:323) at com.dawa.jdk8.StreamTest2.main(StreamTest2.java:26) Suppressed: java.lang.ArithmeticException: first Exception at com.dawa.jdk8.StreamTest2.lambda$main$1(StreamTest2.java:24) at java.util.stream.Streams$1.run(Streams.java:854) ... 2 more
幾種可能的狀況node
備註:遇到問題,javadoc裏面已經寫的很清楚了。每每每一個人都伸手可得的內容,容易最被忽視掉。編程
引入Example,跟源碼。api
public static void main(String[] args) { List<String> list = Arrays.asList("hello", "world", "hello world"); list.stream().forEach(System.out::println); }
來自Collection接口中的默認方法。數組
/** * Returns a sequential {@code Stream} with this collection as its source. * * <p>This method should be overridden when the {@link #spliterator()} * method cannot return a spliterator that is {@code IMMUTABLE}, * {@code CONCURRENT}, or <em>late-binding</em>. (See {@link #spliterator()} * for details.) 當這個 spliterator()沒法返回這三個(不可變的,並行的,延遲綁定的)類型中的一個的話, 這個方法須要被重寫。 * * @implSpec * The default implementation creates a sequential {@code Stream} from the * collection's {@code Spliterator}. 返回一個針對於當前元素的一個串行流。 * * @return a sequential {@code Stream} over the elements in this collection * @since 1.8 */ default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); }
因此,這裏就要先了解一下spliterator()這個方法是怎麼實現的。安全
實現方法和stream()同樣,在Collection接口中的默認方法併發
/** * Creates a {@link Spliterator} over the elements in this collection. * * Implementations should document characteristic values reported by the * spliterator. Such characteristic values are not required to be reported * if the spliterator reports {@link Spliterator#SIZED} and this collection * contains no elements. Spliterator#SIZED,集合,固定大小,而且沒有值。的時候是不用報告的。 --備註:和collectors的characteristic特性值 * * <p>The default implementation should be overridden by subclasses that * can return a more efficient spliterator. In order to * preserve expected laziness behavior for the {@link #stream()} and * {@link #parallelStream()}} methods, spliterators should either have the * characteristic of {@code IMMUTABLE} or {@code CONCURRENT}, or be * <em><a href="Spliterator.html#binding">late-binding</a></em>. * If none of these is practical, the overriding class should describe the * spliterator's documented policy of binding and structural interference, * and should override the {@link #stream()} and {@link #parallelStream()} * methods to create streams using a {@code Supplier} of the spliterator, * as in: 默認的實現,應該被子類所重寫。爲了保留指望的stream()的延遲行爲。分割迭代器的特性值 只有在知足{@code IMMUTABLE} or {@code CONCURRENT}的時候,纔是具備延遲行爲的。 若是上面條件都沒法作的話,重寫的類應該去描述這個分割迭代器的文檔 而且重寫。 用下面的這種方式去定義。 * <pre>{@code * Stream<E> s = StreamSupport.stream(() -> spliterator(), spliteratorCharacteristics) * }</pre> * <p>These requirements ensure that streams produced by the * {@link #stream()} and {@link #parallelStream()} methods will reflect the * contents of the collection as of initiation of the terminal stream * operation. 這些要求確保了由這兩個方法生成的流,反應了流的內容 (在終止流操做執行的一瞬間) * * @implSpec * The default implementation creates a * <em><a href="Spliterator.html#binding">late-binding</a></em> spliterator * from the collections's {@code Iterator}. The spliterator inherits the * <em>fail-fast</em> properties of the collection's iterator. 默認的實現 從集合的迭代器中,建立一個延遲綁定的分割迭代器。 分割迭代器會繼承迭代器的快速失敗的屬性。 * <p> * The created {@code Spliterator} reports {@link Spliterator#SIZED}. 建立的分割迭代器,會攜帶一個 Spliterator#SIZED (固定大小的)的特性值 * * @implNote * The created {@code Spliterator} additionally reports * {@link Spliterator#SUBSIZED}. 還會額外的增長一個Spliterator#SUBSIZED(子大小)的肯定。 * * <p>If a spliterator covers no elements then the reporting of additional * characteristic values, beyond that of {@code SIZED} and {@code SUBSIZED}, * does not aid clients to control, specialize or simplify computation. * However, this does enable shared use of an immutable and empty * spliterator instance (see {@link Spliterators#emptySpliterator()}) for * empty collections, and enables clients to determine if such a spliterator * covers no elements. 若是分割迭代器裏面沒有元素,那麼除了 {@code SIZED} and {@code SUBSIZED}以外其餘的特性,對於計算的控制是沒有幫助做用的。 不過能夠促進空的迭代器的共享使用。 參見: Spliterators#emptySpliterator()、 對於一個空的迭代器能夠判斷是否是沒有元素 * * @return a {@code Spliterator} over the elements in this collection * @since 1.8 */ @Override default Spliterator<E> spliterator() { return Spliterators.spliterator(this, 0); }
那麼,到底什麼是分割迭代器? Spliterator
和Collector收集器同樣,同時提供了collector接口和 Collectors的工具類框架
public final class Spliterators {} public interface Spliterator<T> {}
/** * An object for traversing and partitioning elements of a source. The source * of elements covered by a Spliterator could be, for example, an array, a * {@link Collection}, an IO channel, or a generator function. 一個分割迭代器,是一個對象,用於對源中的元素進行遍歷和分區。 源能夠是:數組,集合,或者IO通道 * * <p>A Spliterator may traverse elements individually ({@link * #tryAdvance tryAdvance()}) or sequentially in bulk * ({@link #forEachRemaining forEachRemaining()}). 一個迭代器能夠一個一個的去遍歷。tryAdvance() 也能夠以塊的方式去遍歷。 forEachRemaining() * * <p>A Spliterator may also partition off some of its elements (using * {@link #trySplit}) as another Spliterator, to be used in * possibly-parallel operations. Operations using a Spliterator that * cannot split, or does so in a highly imbalanced or inefficient * manner, are unlikely to benefit from parallelism. Traversal * and splitting exhaust elements; each Spliterator is useful for only a single * bulk computation. 也可使用 trySplit() 對元素進行分區,造成一個新的元素迭代器。也能夠以並行的方式去操做。 使用Spliterator的操做,是不能分割,或者效率很是低的分割, 若是用並行的話,不會得到很大的收益。 (好比,100個元素,分區分爲 2+98,這種的就是很是低效的。就沒法利用並行的優點了。) 每個分割迭代器,只對本身特定的塊有用。 * * <p>A Spliterator also reports a set of {@link #characteristics()} of its * structure, source, and elements from among {@link #ORDERED}, * {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, {@link #NONNULL}, * {@link #IMMUTABLE}, {@link #CONCURRENT}, and {@link #SUBSIZED}. These may * be employed by Spliterator clients to control, specialize or simplify * computation. For example, a Spliterator for a {@link Collection} would * report {@code SIZED}, a Spliterator for a {@link Set} would report * {@code DISTINCT}, and a Spliterator for a {@link SortedSet} would also * report {@code SORTED}. Characteristics are reported as a simple unioned bit * set. 分割迭代器還會 設置 特性值 {@link #ORDERED}, {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, {@link #NONNULL}, {@link #IMMUTABLE}, {@link #CONCURRENT}, {@link #SUBSIZED}. 這些屬性用來控制特定的某些計算。 好比說,一個 Collection就須要SIZED特性值 Set須要DISTINCT * * Some characteristics additionally constrain method behavior; for example if * {@code ORDERED}, traversal methods must conform to their documented ordering. * New characteristics may be defined in the future, so implementors should not * assign meanings to unlisted values. 不要給沒有列出來的值賦予新的含義。 * * <p><a name="binding">A Spliterator that does not report {@code IMMUTABLE} or * {@code CONCURRENT} is expected to have a documented policy concerning: * when the spliterator <em>binds</em> to the element source; and detection of * structural interference of the element source detected after binding.</a> A * <em>late-binding</em> Spliterator binds to the source of elements at the * point of first traversal, first split, or first query for estimated size, * rather than at the time the Spliterator is created. A Spliterator that is * not <em>late-binding</em> binds to the source of elements at the point of * construction or first invocation of any method. Modifications made to the * source prior to binding are reflected when the Spliterator is traversed. * After binding a Spliterator should, on a best-effort basis, throw * {@link ConcurrentModificationException} if structural interference is * detected. Spliterators that do this are called <em>fail-fast</em>. The * bulk traversal method ({@link #forEachRemaining forEachRemaining()}) of a * Spliterator may optimize traversal and check for structural interference * after all elements have been traversed, rather than checking per-element and * failing immediately. 並非說一個迭代器在建立的時候就被綁定到源上面了。而是在知足首次遍歷,首次分割,首次查詢的時候,才進行綁定。 ConcurrentModificationException,在綁定以前操做,會出現這一行的異常。 叫作 快速失敗。 * * <p>Spliterators can provide an estimate of the number of remaining elements * via the {@link #estimateSize} method. Ideally, as reflected in characteristic * {@link #SIZED}, this value corresponds exactly to the number of elements * that would be encountered in a successful traversal. However, even when not * exactly known, an estimated value value may still be useful to operations * being performed on the source, such as helping to determine whether it is * preferable to split further or traverse the remaining elements sequentially. * * <p>Despite their obvious utility in parallel algorithms, spliterators are not * expected to be thread-safe; instead, implementations of parallel algorithms * using spliterators should ensure that the spliterator is only used by one * thread at a time. This is generally easy to attain via <em>serial * thread-confinement</em>, which often is a natural consequence of typical * parallel algorithms that work by recursive decomposition. A thread calling * {@link #trySplit()} may hand over the returned Spliterator to another thread, * which in turn may traverse or further split that Spliterator. The behaviour * of splitting and traversal is undefined if two or more threads operate * concurrently on the same spliterator. If the original thread hands a * spliterator off to another thread for processing, it is best if that handoff * occurs before any elements are consumed with {@link #tryAdvance(Consumer) * tryAdvance()}, as certain guarantees (such as the accuracy of * {@link #estimateSize()} for {@code SIZED} spliterators) are only valid before * traversal has begun. * serial-thread-confinement : 線程安全圍欄 * <p>Primitive subtype specializations of {@code Spliterator} are provided for * {@link OfInt int}, {@link OfLong long}, and {@link OfDouble double} values. * The subtype default implementations of * {@link Spliterator#tryAdvance(java.util.function.Consumer)} * and {@link Spliterator#forEachRemaining(java.util.function.Consumer)} box * primitive values to instances of their corresponding wrapper class. Such * boxing may undermine any performance advantages gained by using the primitive * specializations. To avoid boxing, the corresponding primitive-based methods * should be used. tryAdvance()方法和forEachRemaining() 提供了原生子類型的特化, int, long, doule 等,子類型默認的實現。 避免包裝類型裝箱拆箱操做。 以下。 For example, 以下特化版本. * {@link Spliterator.OfInt#tryAdvance(java.util.function.IntConsumer)} * and {@link Spliterator.OfInt#forEachRemaining(java.util.function.IntConsumer)} * should be used in preference to * {@link Spliterator.OfInt#tryAdvance(java.util.function.Consumer)} and * {@link Spliterator.OfInt#forEachRemaining(java.util.function.Consumer)}. * Traversal of primitive values using boxing-based methods * {@link #tryAdvance tryAdvance()} and * {@link #forEachRemaining(java.util.function.Consumer) forEachRemaining()} * does not affect the order in which the values, transformed to boxed values, * are encountered. * * @apiNote * <p>Spliterators, like {@code Iterator}s, are for traversing the elements of * a source. The {@code Spliterator} API was designed to support efficient * parallel traversal in addition to sequential traversal, by supporting * decomposition as well as single-element iteration. In addition, the * protocol for accessing elements via a Spliterator is designed to impose * smaller per-element overhead than {@code Iterator}, an d to avoid the inherent * race involved in having separate methods for {@code hasNext()} and * {@code next()}. Spliterator支持高效的,並行的操做。 支持解耦,分解,氮元素的遍歷。 此外,經過accessing協議。。。 相對於 Iterator,遍歷元素的時候成本更低。 緣由: 以前的{@code hasNext()} and {@code next()}.搭配使用存在競爭。 如今直接使用一個tryAdvance()方法就解決了這兩個方法實現的事情。 * * <p>For mutable sources, arbitrary and non-deterministic behavior may occur if * the source is structurally interfered with (elements added, replaced, or * removed) between the time that the Spliterator binds to its data source and * the end of traversal. For example, such interference will produce arbitrary, * non-deterministic results when using the {@code java.util.stream} framework. 若是源在結構上被修改了(增刪改),在綁定迭代器以後和執行完畢以前這段時間內進行任意修改。 行爲就是不肯定的了。 因此在使用流框架的時候,要求源是不可變的 * * <p>Structural interference of a source can be managed in the following ways * (in approximate order of decreasing desirability): 源結構上的修改,是能夠經過以下幾個方式去修改的 * <ul> * <li>The source cannot be structurally interfered with. 如,源是不容許被修改的。 * <br>For example, an instance of * {@link java.util.concurrent.CopyOnWriteArrayList} is an immutable source. * A Spliterator created from the source reports a characteristic of * {@code IMMUTABLE}.</li> 如:CopyOnWriteArrayList是一個不可變的源。 先拷貝,再追加。 (可是效率會降低。)適合讀多寫少的操做。 * <li>The source manages concurrent modifications. 源自己本身去管理併發。 * <br>For example, a key set of a {@link java.util.concurrent.ConcurrentHashMap} * is a concurrent source. A Spliterator created from the source reports a * characteristic of {@code CONCURRENT}.</li> 如:ConcurrentHashMap 。 建立的是併發源 * <li>The mutable source provides a late-binding and fail-fast Spliterator. * <br>Late binding narrows the window during which interference can affect * the calculation; fail-fast detects, on a best-effort basis, that structural * interference has occurred after traversal has commenced and throws * {@link ConcurrentModificationException}. For example, {@link ArrayList}, * and many other non-concurrent {@code Collection} classes in the JDK, provide * a late-binding, fail-fast spliterator.</li> 可變的源提供了延遲綁定和快速失敗的迭代分割器。 會限制時間點的縮短。 若是在遍歷中修改,則會拋出ConcurrentModificationException。 * <li>The mutable source provides a non-late-binding but fail-fast Spliterator. * <br>The source increases the likelihood of throwing * {@code ConcurrentModificationException} since the window of potential * interference is larger.</li> * <li>The mutable source provides a late-binding and non-fail-fast Spliterator. * <br>The source risks arbitrary, non-deterministic behavior after traversal * has commenced since interference is not detected. * </li> * <li>The mutable source provides a non-late-binding and non-fail-fast * Spliterator. * <br>The source increases the risk of arbitrary, non-deterministic behavior * since non-detected interference may occur after construction. * </li> 總結。 1. 源是否是併發的 2. 是否是快速綁定的,是否是快速失敗的(2*2 組合的四種狀況。) * </ul> * 串行案例 * <p><b>Example.</b> Here is a class (not a very useful one, except * for illustration) that maintains an array in which the actual data * are held in even locations, and unrelated tag data are held in odd * locations. Its Spliterator ignores the tags. 如:類維護了一個數組。 實際的數據是在偶數的位置上存放。不想管的標籤數據是存放在奇數位置上。 * * <pre> {@code * class TaggedArray<T> { * private final Object[] elements; // immutable after construction * TaggedArray(T[] data, Object[] tags) { * int size = data.length; * if (tags.length != size) throw new IllegalArgumentException(); * this.elements = new Object[2 * size]; * for (int i = 0, j = 0; i < size; ++i) { * elements[j++] = data[i]; * elements[j++] = tags[i]; * } * } * * public Spliterator<T> spliterator() { * return new TaggedArraySpliterator<>(elements, 0, elements.length); * } * * static class TaggedArraySpliterator<T> implements Spliterator<T> { * private final Object[] array; * private int origin; // current index, advanced on split or traversal * private final int fence; // one past the greatest index * * TaggedArraySpliterator(Object[] array, int origin, int fence) { * this.array = array; this.origin = origin; this.fence = fence; * } * * public void forEachRemaining(Consumer<? super T> action) { * for (; origin < fence; origin += 2) * action.accept((T) array[origin]); * } * * public boolean tryAdvance(Consumer<? super T> action) { * if (origin < fence) { * action.accept((T) array[origin]); * origin += 2; * return true; * } * else // cannot advance * return false; * } * * public Spliterator<T> trySplit() { * int lo = origin; // divide range in half * int mid = ((lo + fence) >>> 1) & ~1; // force midpoint to be even * if (lo < mid) { // split out left half * origin = mid; // reset this Spliterator's origin * return new TaggedArraySpliterator<>(array, lo, mid); * } * else // too small to split * return null; * } * * public long estimateSize() { * return (long)((fence - origin) / 2); * } * * public int characteristics() { * return ORDERED | SIZED | IMMUTABLE | SUBSIZED; * } * } * }}</pre> * 並行案例: * <p>As an example how a parallel computation framework, such as the * {@code java.util.stream} package, would use Spliterator in a parallel * computation, here is one way to implement an associated parallel forEach, * that illustrates the primary usage idiom of splitting off subtasks until * the estimated amount of work is small enough to perform * sequentially. Here we assume that the order of processing across * subtasks doesn't matter; different (forked) tasks may further split * and process elements concurrently in undetermined order. This * example uses a {@link java.util.concurrent.CountedCompleter}; * similar usages apply to other parallel task constructions. * * <pre>{@code * static <T> void parEach(TaggedArray<T> a, Consumer<T> action) { * Spliterator<T> s = a.spliterator(); * long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8); * new ParEach(null, s, action, targetBatchSize).invoke(); * } * * static class ParEach<T> extends CountedCompleter<Void> { * final Spliterator<T> spliterator; * final Consumer<T> action; * final long targetBatchSize; * * ParEach(ParEach<T> parent, Spliterator<T> spliterator, * Consumer<T> action, long targetBatchSize) { * super(parent); * this.spliterator = spliterator; this.action = action; * this.targetBatchSize = targetBatchSize; * } * * public void compute() { * Spliterator<T> sub; * while (spliterator.estimateSize() > targetBatchSize && * (sub = spliterator.trySplit()) != null) { * addToPendingCount(1); * new ParEach<>(this, sub, action, targetBatchSize).fork(); * } * spliterator.forEachRemaining(action); * propagateCompletion(); * } * }}</pre> * * @implNote * If the boolean system property {@code org.openjdk.java.util.stream.tripwire} * is set to {@code true} then diagnostic warnings are reported if boxing of * primitive values occur when operating on primitive subtype specializations. * * @param <T> the type of elements returned by this Spliterator * * @see Collection * @since 1.8 */
/** * If a remaining element exists, performs the given action on it, * returning {@code true}; else returns {@code false}. If this * Spliterator is {@link #ORDERED} the action is performed on the * next element in encounter order. Exceptions thrown by the * action are relayed to the caller. * * @param action The action * @return {@code false} if no remaining elements existed * upon entry to this method, else {@code true}. * @throws NullPointerException if the specified action is null */ boolean tryAdvance(Consumer<? super T> action);
/** * Performs the given action for each remaining element, sequentially in * the current thread, until all elements have been processed or the action * throws an exception. If this Spliterator is {@link #ORDERED}, actions * are performed in encounter order. Exceptions thrown by the action * are relayed to the caller. * * @implSpec * The default implementation repeatedly invokes {@link #tryAdvance} until * it returns {@code false}. It should be overridden whenever possible. * * @param action The action * @throws NullPointerException if the specified action is null */ default void forEachRemaining(Consumer<? super T> action) { do { } while (tryAdvance(action)); }
/** * If this spliterator can be partitioned, returns a Spliterator * covering elements, that will, upon return from this method, not * be covered by this Spliterator. 若是這個分割迭代器可以被進行分割。就會返回一個 涵蓋這個元素的Spliterator, 分割出來的新的Spliterator可能會被繼續分割,剩下的繼續又當前的Spliterator涵蓋 * * <p>If this Spliterator is {@link #ORDERED}, the returned Spliterator * must cover a strict prefix of the elements. 若是 Spliterator is {@link #ORDERED}。返回的必須是ORDERED的 * * <p>Unless this Spliterator covers an infinite number of elements, * repeated calls to {@code trySplit()} must eventually return {@code null}. 除非這個 Spliterator 涵蓋的事一個無限的元素。 不然,必須被確認返回個數是肯定的。 重複的去繼續分割,分割到不能再分割。 (必定會有這樣的狀況。) * Upon non-null return: * <ul> * <li>the value reported for {@code estimateSize()} before splitting, * must, after splitting, be greater than or equal to {@code estimateSize()} * for this and the returned Spliterator; and</li> * <li>if this Spliterator is {@code SUBSIZED}, then {@code estimateSize()} * for this spliterator before splitting must be equal to the sum of * {@code estimateSize()} for this and the returned Spliterator after * splitting.</li> * </ul> 若是不會空: 分割前的 estimateSize()的返回值,必須大於等於分割以後estimateSize()的返回值。 若是 Spliterator is {@code SUBSIZED},那麼 分割以前 estimateSize()的大小,必須等於 分割以後的 estimateSize() 和返回來的值的大小。(分割先後:必須 8 = 4+4.) * * <p>This method may return {@code null} for any reason, * including emptiness, inability to split after traversal has * commenced, data structure constraints, and efficiency * considerations. 這個放個出於如下緣由,都會返回Null值 1. emptiness * * @apiNote * An ideal {@code trySplit} method efficiently (without * traversal) divides its elements exactly in half, allowing * balanced parallel computation. Many departures from this ideal * remain highly effective; for example, only approximately * splitting an approximately balanced tree, or for a tree in * which leaf nodes may contain either one or two elements, * failing to further split these nodes. However, large * deviations in balance and/or overly inefficient {@code * trySplit} mechanics typically result in poor parallel * performance. @API文檔 一種理想的trySplit()方法,會剛好將元素分爲兩半。容許平衡的並行計算。 不少狀況下違背了這種理想的狀況。 好比說:只是分割一個嫉妒不平衡的一個數,數中只有兩個節點。等。不能再次進行分割。 然而,很不平衡的這種機制,會致使併發效率的極度下降。 * * @return a {@code Spliterator} covering some portion of the * elements, or {@code null} if this spliterator cannot be split 返回一個Spliterator */ Spliterator<T> trySplit();
/** * Returns an estimate of the number of elements that would be * encountered by a {@link #forEachRemaining} traversal, or returns {@link * Long#MAX_VALUE} if infinite, unknown, or too expensive to compute. 返回元素數量的估算值。(會被forEachRemaining 遍歷的元素) infinite, unknown, or too expensive to compute.這幾種狀況會返回:MAX_VALUE * * <p>If this Spliterator is {@link #SIZED} and has not yet been partially * traversed or split, or this Spliterator is {@link #SUBSIZED} and has * not yet been partially traversed, this estimate must be an accurate * count of elements that would be encountered by a complete traversal. * Otherwise, this estimate may be arbitrarily inaccurate, but must decrease * as specified across invocations of {@link #trySplit}. 若是Spliterator是SIZED 或者是SUBSIZED 。那個 這個元素的estimate值必定是精確的。 然而,必需要減小 trySplit 的調用。 * * @apiNote * Even an inexact estimate is often useful and inexpensive to compute. * For example, a sub-spliterator of an approximately balanced binary tree * may return a value that estimates the number of elements to be half of * that of its parent; if the root Spliterator does not maintain an * accurate count, it could estimate size to be the power of two * corresponding to its maximum depth. 甚至一個不太精確的估算,也是有用的。 * * @return the estimated size, or {@code Long.MAX_VALUE} if infinite, * unknown, or too expensive to compute. */ long estimateSize();
/** * Convenience method that returns {@link #estimateSize()} if this * Spliterator is {@link #SIZED}, else {@code -1}. 若是Spliterator是SIZED的話, estimateSize就會返回肯定的大小。 * @implSpec * The default implementation returns the result of {@code estimateSize()} * if the Spliterator reports a characteristic of {@code SIZED}, and * {@code -1} otherwise. * * @return the exact size, if known, else {@code -1}. */ default long getExactSizeIfKnown() { return (characteristics() & SIZED) == 0 ? -1L : estimateSize(); }
/** * Returns a set of characteristics of this Spliterator and its * elements. The result is represented as ORed values from {@link * #ORDERED}, {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, * {@link #NONNULL}, {@link #IMMUTABLE}, {@link #CONCURRENT}, * {@link #SUBSIZED}. Repeated calls to {@code characteristics()} on * a given spliterator, prior to or in-between calls to {@code trySplit}, * should always return the same result. 返回這個Spliterator的特性值的集合。 {@link#ORDERED}, {@link #DISTINCT}, {@link #SORTED}, {@link #SIZED}, {@link #NONNULL}, {@link #IMMUTABLE}, {@link #CONCURRENT}, {@link #SUBSIZED} 這8個,在下面有定義。 * * <p>If a Spliterator reports an inconsistent set of * characteristics (either those returned from a single invocation * or across multiple invocations), no guarantees can be made * about any computation using this Spliterator. * * @apiNote The characteristics of a given spliterator before splitting * may differ from the characteristics after splitting. For specific * examples see the characteristic values {@link #SIZED}, {@link #SUBSIZED} * and {@link #CONCURRENT}. 具體的例子看下面的說明。 * * @return a representation of characteristics */ int characteristics();
/** * Returns {@code true} if this Spliterator's {@link * #characteristics} contain all of the given characteristics. * * @implSpec * The default implementation returns true if the corresponding bits * of the given characteristics are set. * * @param characteristics the characteristics to check for * @return {@code true} if all the specified characteristics are present, * else {@code false} */ default boolean hasCharacteristics(int characteristics) { return (characteristics() & characteristics) == characteristics; }
/** * If this Spliterator's source is {@link #SORTED} by a {@link Comparator}, * returns that {@code Comparator}. If the source is {@code SORTED} in * {@linkplain Comparable natural order}, returns {@code null}. Otherwise, * if the source is not {@code SORTED}, throws {@link IllegalStateException}. 若是源是有序的,返回用於排序的 Comparator 若是是按照天然排序的,就返回空 (就不須要比較器) 不然就拋出異常, * * @implSpec * The default implementation always throws {@link IllegalStateException}. * * @return a Comparator, or {@code null} if the elements are sorted in the * natural order. * @throws IllegalStateException if the spliterator does not report * a characteristic of {@code SORTED}. */ default Comparator<? super T> getComparator() { throw new IllegalStateException(); }
ORDERED DISTINCT SORTED SIZED NONNULL IMMUTABLE CONCURRENT SUBSIZED //更多的是用在併發的時候,指定執行哪些內容。
/** * Characteristic value signifying that an encounter order is defined for * elements. If so, this Spliterator guarantees that method * {@link #trySplit} splits a strict prefix of elements, that method * {@link #tryAdvance} steps by one element in prefix order, and that * {@link #forEachRemaining} performs actions in encounter order. * * <p>A {@link Collection} has an encounter order if the corresponding * {@link Collection#iterator} documents an order. If so, the encounter * order is the same as the documented order. Otherwise, a collection does * not have an encounter order. * * @apiNote Encounter order is guaranteed to be ascending index order for * any {@link List}. But no order is guaranteed for hash-based collections * such as {@link HashSet}. Clients of a Spliterator that reports * {@code ORDERED} are expected to preserve ordering constraints in * non-commutative parallel computations. */ public static final int ORDERED = 0x00000010; /** * Characteristic value signifying that, for each pair of * encountered elements {@code x, y}, {@code !x.equals(y)}. This * applies for example, to a Spliterator based on a {@link Set}. */ public static final int DISTINCT = 0x00000001; /** * Characteristic value signifying that encounter order follows a defined * sort order. If so, method {@link #getComparator()} returns the associated * Comparator, or {@code null} if all elements are {@link Comparable} and * are sorted by their natural ordering. * * <p>A Spliterator that reports {@code SORTED} must also report * {@code ORDERED}. * * @apiNote The spliterators for {@code Collection} classes in the JDK that * implement {@link NavigableSet} or {@link SortedSet} report {@code SORTED}. */ public static final int SORTED = 0x00000004; /** * Characteristic value signifying that the value returned from * {@code estimateSize()} prior to traversal or splitting represents a * finite size that, in the absence of structural source modification, * represents an exact count of the number of elements that would be * encountered by a complete traversal. 在執行遍歷或者分割以前,由estimateSize返回的值,表示一個有序的大小。 表示元素的數量的精確的值。 * * @apiNote Most Spliterators for Collections, that cover all elements of a * {@code Collection} report this characteristic. Sub-spliterators, such as * those for {@link HashSet}, that cover a sub-set of elements and * approximate their reported size do not. 大部分對於Collections的分割迭代器,通常都會有這個特性值。 */ public static final int SIZED = 0x00000040; /** * Characteristic value signifying that the source guarantees that * encountered elements will not be {@code null}. (This applies, * for example, to most concurrent collections, queues, and maps.) */ public static final int NONNULL = 0x00000100; /** * Characteristic value signifying that the element source cannot be * structurally modified; that is, elements cannot be added, replaced, or * removed, so such changes cannot occur during traversal. A Spliterator * that does not report {@code IMMUTABLE} or {@code CONCURRENT} is expected * to have a documented policy (for example throwing * {@link ConcurrentModificationException}) concerning structural * interference detected during traversal. 指定元素的源是不能被修改的,不能被(be added, replaced, or removed)。 在執行的時候,若是發現被修改,沒有返回,則會拋出ConcurrentModificationException併發修改異常。 */ public static final int IMMUTABLE = 0x00000400; /** * Characteristic value signifying that the element source may be safely * concurrently modified (allowing additions, replacements, and/or removals) * by multiple threads without external synchronization. If so, the * Spliterator is expected to have a documented policy concerning the impact * of modifications during traversal. 表示元素的源可以安全的被併發修改。容許 modified (allowing additions, replacements, and/or removals)。 不須要外部的同步化的操做。Spliterator的提供了容許被修改的策略。 * * <p>A top-level Spliterator should not report both {@code CONCURRENT} and * {@code SIZED}, since the finite size, if known, may change if the source * is concurrently modified during traversal. Such a Spliterator is * inconsistent and no guarantees can be made about any computation using * that Spliterator. Sub-spliterators may report {@code SIZED} if the * sub-split size is known and additions or removals to the source are not * reflected when traversing. 頂層的Spliterator 不該該同時返回:{@code CONCURRENT} and {@code SIZED}。 由於二者之間存在必定的矛盾性。 這個的Spliterator 是不一直到, 獲得的Sub-spliterators 可能會返回SIZED。 * * @apiNote Most concurrent collections maintain a consistency policy * guaranteeing accuracy with respect to elements present at the point of * Spliterator construction, but possibly not reflecting subsequent * additions or removals. 大可能是的這種併發性的集合,都會被維護必定的策略。 :原有的Spliterator ,不會去影響子的Spliterator */ public static final int CONCURRENT = 0x00001000; /** * Characteristic value signifying that all Spliterators resulting from * {@code trySplit()} will be both {@link #SIZED} and {@link #SUBSIZED}. * (This means that all child Spliterators, whether direct or indirect, will * be {@code SIZED}.) * * <p>A Spliterator that does not report {@code SIZED} as required by * {@code SUBSIZED} is inconsistent and no guarantees can be made about any * computation using that Spliterator. A Spliterator若是沒有返回要求的SIZED。 是沒有明確的保證的。 * * @apiNote Some spliterators, such as the top-level spliterator for an * approximately balanced binary tree, will report {@code SIZED} but not * {@code SUBSIZED}, since it is common to know the size of the entire tree * but not the exact sizes of subtrees. 有一些Spliterator。如二叉樹的整個樹的大小,咱們得知總的數,可是不知道子的數。 */ public static final int SUBSIZED = 0x00004000;
以上就是關於spliterator的interface全部內容。
Spliterator都支持哪些事情?上面的8個方法。就是具體功能的實現。
專門針對於原生的迭代器(int, long, double)
/** * A Spliterator specialized for primitive values. * * @param <T> the type of elements returned by this Spliterator. The * type must be a wrapper type for a primitive type, such as {@code Integer} * for the primitive {@code int} type. * @param <T_CONS> the type of primitive consumer. The type must be a * primitive specialization of {@link java.util.function.Consumer} for * {@code T}, such as {@link java.util.function.IntConsumer} for * {@code Integer}. * @param <T_SPLITR> the type of primitive Spliterator. The type must be * a primitive specialization of Spliterator for {@code T}, such as * {@link Spliterator.OfInt} for {@code Integer}. * * @see Spliterator.OfInt * @see Spliterator.OfLong * @see Spliterator.OfDouble * @since 1.8 */ public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>> extends Spliterator<T> { @Override T_SPLITR trySplit(); /** * If a remaining element exists, performs the given action on it, * returning {@code true}; else returns {@code false}. If this * Spliterator is {@link #ORDERED} the action is performed on the * next element in encounter order. Exceptions thrown by the * action are relayed to the caller. * * @param action The action * @return {@code false} if no remaining elements existed * upon entry to this method, else {@code true}. * @throws NullPointerException if the specified action is null */ @SuppressWarnings("overloads") boolean tryAdvance(T_CONS action); /** * Performs the given action for each remaining element, sequentially in * the current thread, until all elements have been processed or the * action throws an exception. If this Spliterator is {@link #ORDERED}, * actions are performed in encounter order. Exceptions thrown by the * action are relayed to the caller. * * @implSpec * The default implementation repeatedly invokes {@link #tryAdvance} * until it returns {@code false}. It should be overridden whenever * possible. * * @param action The action * @throws NullPointerException if the specified action is null */ @SuppressWarnings("overloads") default void forEachRemaining(T_CONS action) { do { } while (tryAdvance(action)); } }
提供了三個特化版本。實現了OfPrimitive接口。
public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> { @Override OfInt trySplit(); @Override boolean tryAdvance(IntConsumer action); @Override default void forEachRemaining(IntConsumer action) { do { } while (tryAdvance(action)); } /** * {@inheritDoc} * @implSpec * If the action is an instance of {@code IntConsumer} then it is cast * to {@code IntConsumer} and passed to * {@link #tryAdvance(java.util.function.IntConsumer)}; otherwise * the action is adapted to an instance of {@code IntConsumer}, by * boxing the argument of {@code IntConsumer}, and then passed to * {@link #tryAdvance(java.util.function.IntConsumer)}. */ @Override default boolean tryAdvance(Consumer<? super Integer> action) { if (action instanceof IntConsumer) { return tryAdvance((IntConsumer) action); } else { if (Tripwire.ENABLED) Tripwire.trip(getClass(), "{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)"); return tryAdvance((IntConsumer) action::accept); } } /** * {@inheritDoc} * @implSpec * If the action is an instance of {@code IntConsumer} then it is cast * to {@code IntConsumer} and passed to * {@link #forEachRemaining(java.util.function.IntConsumer)}; otherwise * the action is adapted to an instance of {@code IntConsumer}, by * boxing the argument of {@code IntConsumer}, and then passed to * {@link #forEachRemaining(java.util.function.IntConsumer)}. */ @Override default void forEachRemaining(Consumer<? super Integer> action) { if (action instanceof IntConsumer) { forEachRemaining((IntConsumer) action); } else { if (Tripwire.ENABLED) Tripwire.trip(getClass(), "{0} calling Spliterator.OfInt.forEachRemaining((IntConsumer) action::accept)"); forEachRemaining((IntConsumer) action::accept); } } }
問題:要知道Consumer和IntConsumer是沒有任何繼承關係的話,他們是怎麼實現類型轉換的呢?
default boolean tryAdvance(Consumer<? super Integer> action) { if (action instanceof IntConsumer) { return tryAdvance((IntConsumer) action); }
若是是純粹的面向對象的,這種現象是徹底不可以存在的。
可是若是是在這函數式編程的狀況下,是可以存在的。
緣由以下:
用代碼來解釋。