/** * 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. * <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. Spliterator 能夠對元素進行分區。 分紅新的Spliterator。 而且以並行的操做來實行。 若是不能分割這些操做,則不能經過並行操做受益。 遍歷和分割都會對那一小塊是有用的、 * <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. 特性值:ORDERED 有序的, DISTINCT 不一樣的,SORTED 帶排序的,SIZED 肯定大小的, NONNULL 非空的, IMMUTABLE, CONCURRENT ,SUBSIZED 這些特性能夠在客戶端使用,用來簡化計算。是以位操做的形式來表示的。 collector中是以枚舉形式來表示的。 * 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. 當Spliterator 綁定到源上時 , 要考慮 IMMUTABLE 和 CONCURRENT 。 延遲迭代器會在第一次遍歷或者分割或者查詢大小的時候綁定在源上邊。而不是在建立的時候就被綁定在源上了。 非延遲迭代器是在建立的時候就被綁定在源上了。 在迭代器綁定後對源進行了修改。迭代器就能反應出來拋出異常ConcurrentModificationException。 forEachRemaining()會優化遍歷,是在全部元素都被操做以後進行操做,而不是一個元素一個元素的檢測、 * <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. 若是 特性值 SIZED 。 那麼將要遍歷的數量是肯定的。 若是不包含SIZED,一個估算的值對於源的操做也是有幫助的。 * <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. 分割迭代器並不確保是線程安全的。相反 應該確保分割迭代器一次被一個線程操做、 能夠經過遞歸的方式來實現。 * <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. 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}, and to avoid the inherent * race involved in having separate methods for {@code hasNext()} and * {@code next()}. 分割迭代器 就像迭代器同樣。 用來遍歷源當中的元素的。 Spliterator也支持並行的操做。方式是經過解耦,分解,單元素的遍歷迭代。 Spliterator相比於Iterator來講,成本更低。tryAdvance()本質上也避免了hasNext()和next() 的資源上的競爭。 * <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 適合於 讀多寫少的場景。 他是一個不可變的源。會返回一個特性值IMMUTABLE * <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> 建立併發源、 特性值 CONCURRENT * <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> * <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> * </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; * } * // 嘗試進行分割, 儘可能均勻的分割成兩半. 不成功返回null * 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. * 若是 {@code org.openjdk.java.util.stream.tripwire} 被設置成true, 則會給出警告。 * @param <T> the type of elements returned by this Spliterator * * @see Collection * @since 1.8 */ public interface Spliterator<T> { // 。。。 下方列舉幾個 }
/** * 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 * <p>If this Spliterator is {@link #ORDERED}, the returned Spliterator * must cover a strict prefix of the elements. *若是Spliterator是有序的,則返回的也應該是有序的Spliterator * <p>Unless this Spliterator covers an infinite number of elements, * repeated calls to {@code trySplit()} must eventually return {@code null}. 除非Spliterator 返回的是無窮的元素,其他的最終返回一個null . 表示不能再繼續分割了。 * Upon non-null return: 若是返回不爲Null的話, * <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> 分割前的estimateSize>= 返回的estimateSize * <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> 若是大小是固定的。則分割後的 estimateSize 的總和 等於分割前的 estimateSize * </ul> * * <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. * * @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. *理想狀況下,是從中間分割的,容許並行計算。不少狀況下不知足這種的、 然而沒有效率的分割,會下降效率 * @return a {@code Spliterator} covering some portion of the * elements, or {@code null} if this spliterator cannot be split */ //嘗試分割。 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. * * <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}. * 分的越少,estimateSize要比原來的個數要小。 * @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();
/** * 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. 一個特性值的集合。 重複的調用characteristics 在spliterator以前或者當中,會返回相同的結果。 * <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. * 默認的話,包含 會返回true * @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}. * * @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}. */ //有序的話 返回一個Null。 其餘狀況 拋異常 default Comparator<? super T> getComparator() { throw new IllegalStateException(); }
/** * 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. */ 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. * * <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. * * @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. */ public static final int CONCURRENT = 0x00001000;
/** * 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)); } }
/** * A Spliterator specialized for {@code int} values. * @since 1.8 */ 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); } } }
IntConsumer 和 Consumer 是沒有任何的關聯關係 的。可是爲何能(IntConsumer)Consumerjava
由於jdk自帶裝箱拆箱操做。 int 和 integer 重疊了。node