Spliterator

1. 簡(jiǎn)介

我們常常遍歷數(shù)組,集合少梁,map等洛口,都是在單線程里面遍歷的 ,jdk1.8 之后凯沪,出現(xiàn)Spilterator 可以讓我們?cè)诙嗑€程下遍歷集合绍弟,基本思想就是把一個(gè)集合分割成多個(gè)小集合由多個(gè)線程遍歷

2.接口方法介紹

// 如果有,則遍歷下一個(gè)元素
tryAdvance
// 遍歷 剩余的元素
forEachRemaining
// 就是嘗試分割著洼, 分割失斦燎病(元素太少,或者已經(jīng)開(kāi)始遍歷身笤,或者獲得分割器x效率低下)返回null 豹悬,每次分割一半
trySplit
// 返回估算的大小,如果SIZED 和SUBSIZED 那么返回 大小是確定的
estimateSize
// 就是調(diào)用上面的方法液荸, 如果不確定那么返回-1
getExactSizeIfKnown
//這個(gè)分割器的特性
characteristics
// 判斷此分割器是否含有這個(gè)特性 (使用 按位與操作的)
hasCharacteristics
// 獲取比較器瞻佛,如果是自然排序的,返回null, 如果是比較器排序的返回比較器娇钱,否則跑出一次
getComparator

3. 分割器的特性介紹

// 指定這個(gè)分割器按照順序取出元素 如數(shù)組伤柄,List產(chǎn)生的Spiterator都是有這個(gè)特性的
ORDERED 
//  不重復(fù)  如Set 
DISTINCT
// 排好序的 如 Set
SORTED
// 有固定大小的 ,我們常常使用非多線程安全集合文搂,如Set,List都是适刀,并發(fā)的集合在Spilerator分割和遍歷的時(shí)候是會(huì)發(fā)生變化的
SIZED
// 里面的元素不是空的
NONNULL
// 集合是不可變的 ,那么也具有 SIZED和SUBSIZED
IMMUTABLE
// 支持并發(fā)的 煤蹭,那么一般沒(méi)有SIZED和SUBSIZED 如ConcurrentSkipListSet
CONCURRENT笔喉、
// 分割后的子大小也是不變的       
SUBSIZED

注意 : 子Spliterator 與父Spliterator的特性可能不一樣

4.子接口介紹

這些子接口使用的是原生類(lèi)型,執(zhí)行速度比包裝類(lèi)型快很多

4.1OfPrimitive

 public interface OfPrimitive<T, T_CONS, T_SPLITR extends Spliterator.OfPrimitive<T, T_CONS, T_SPLITR>>
            extends Spliterator<T>
 // T :我們?cè)氐念?lèi)型
 // T_CONS: 我們forEachRemaining 消費(fèi)的類(lèi)型硝皂,是IntConsumer或者LongConsumer或者DoubleCosumer中的一個(gè)
// T_SPLITR : OfPrimitive子接口的類(lèi)型
// 其實(shí)這個(gè)接口就起抽象 原子類(lèi)型的Spiterator

4.2OfInt

對(duì)OfPrimitive的實(shí)現(xiàn) T 用的是Integer ,而且還添加了一個(gè)boolean
tryAdvance(IntConsumer action);注意參數(shù)是IntConsumer
默認(rèn)實(shí)現(xiàn)了Spilterator的tryAdvance()方法常挚,實(shí)現(xiàn)如下

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);
            }

這個(gè)方法的實(shí)現(xiàn)很奇怪,奇怪是action 實(shí)現(xiàn)了Consumer接口,又實(shí)現(xiàn)了IntConsumer稽物,然而Consumer和IntConsumer不是父子關(guān)系奄毡,其實(shí)這個(gè)兩個(gè)接口的lamdab表示式子是相同的

Consumer consumer = System.out::println;
IntConsumer intConsumer = System.out::println;
// 但是這個(gè)兩個(gè)之間是不能相互強(qiáng)轉(zhuǎn)的 ,所以認(rèn)為是這樣的有一個(gè)子類(lèi)實(shí)現(xiàn)了著兩個(gè)接口即可,便可以理解了
 static  class ConsumerImpl implements Consumer<Integer>,IntConsumer{

        @Override
        public void accept(Integer value) {

        }

        @Override
        public void accept(int value) {

        }
    }

4.3 OfLong

跟OfInt一樣 贝或,只不過(guò) T 就是Long ,而 Consumer是就是LongConsumer

4.4OfDouble

跟OfInt一樣 吼过,只不過(guò) T 就是Double,而 Consumer是就是DoubleConsumer

5 Spliterotors介紹

這類(lèi)和Spliterator 的關(guān)系就像 Collections 和Collection的關(guān)系锐秦,他是Spliterator的伴生對(duì)象。作用就是用來(lái)創(chuàng)建Spliterator的

// Spliterator.spliterator 方法 有很多重載方法那先,基于原生類(lèi)型和引用類(lèi)型的數(shù)組农猬,還有集合的等等
// 如: 從int[]中創(chuàng)建 赡艰,指定特行一般就是 SIZED |SUBSIZE|ORDERED|NONULL
Spliterator.OfInt spliterator(int[] array,  int additionalCharacteristics) 
Spliterator<T> spliterator(Object[] array, int additionalCharacteristics)
spliterator(Collection<? extends T> c,  int characteristics)
//等等售淡。。

6 簡(jiǎn)單HelloWorld

這個(gè)例子是用 Spliterator 和 ForkJoin結(jié)合使用的慷垮。他們的特性剛剛切合

package liusheng.main.hello;

import java.util.Random;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;

public class SpliteratorHelloWorld {
    public static void main(String[] args) {
        // 我們生成1000個(gè)隨機(jī)數(shù)
        Random random = new Random();
        int[] array = IntStream.range(0, 1000).map(i-> random.nextInt(100)).toArray();
        // 創(chuàng)建分割器
        Spliterator.OfInt sumSpliterator = Spliterators.spliterator(array, Spliterator.ORDERED | Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.NONNULL);
        Sum sum = new Sum(sumSpliterator);
        // 因?yàn)槲覀兪褂玫腇orkJoinTask ,所以我們要?jiǎng)?chuàng)建 ForkJoinPool
        ForkJoinPool commonPool = ForkJoinPool.commonPool();
        sum  = (Sum) commonPool.submit(sum);

        System.out.println(sum.join());
    }
    /**
     * 因?yàn)檫@里使用是原生類(lèi)型 揖闸,所以我們使用原生類(lèi)型Spliterator
     */
    static class Sum extends RecursiveTask<Long> {
        private Spliterator.OfInt spiterator;

        public Sum(Spliterator.OfInt spiterator) {
            this.spiterator = spiterator;
        }

        @Override
        protected Long compute() {
            // 如果是100個(gè)以?xún)?nèi),直接計(jì)算 原生類(lèi)型的數(shù)組的大小是不會(huì)發(fā)生變化的料身,所以這個(gè)是精確的
            if (spiterator.estimateSize() <= 100) {
                long[] sum = new long[1];
                spiterator.forEachRemaining((IntConsumer) i -> {
                    sum[0] += i;
                });
                return sum[0];
            }
            // 進(jìn)行分割
            Spliterator.OfInt split = spiterator.trySplit();
            if (split != null) {
                Sum left = new Sum(spiterator);
                Sum right = new Sum(split);
                //計(jì)算
                left.fork();
                //計(jì)算
                right.fork();
                //等待結(jié)果
                return left.join() +
                right.join();

            }
            return 0L;
        }
    }
}

7.深入使用

暫時(shí)還沒(méi)有想到以后再補(bǔ)吧汤纸。。芹血。贮泞。

8.總結(jié)

Spliterator的主要作用就是為了提高遍歷速度,當(dāng)每次分兩塊大小相等的時(shí)候幔烛,效率是最高的啃擦,但是這是理想情況,有時(shí)饿悬,當(dāng)數(shù)據(jù)結(jié)構(gòu)不理想的時(shí)候令蛉,或者分割相差太大,那么返回會(huì)降低效率狡恬。所以我們要在合適的場(chǎng)景下使用珠叔。
有什么錯(cuò)誤的地方望大佬指正,相互學(xué)習(xí)嘛弟劲。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祷安,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兔乞,更是在濱河造成了極大的恐慌辆憔,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件报嵌,死亡現(xiàn)場(chǎng)離奇詭異虱咧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)锚国,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)腕巡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人血筑,你說(shuō)我怎么就攤上這事绘沉〖彘梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵车伞,是天一觀的道長(zhǎng)择懂。 經(jīng)常有香客問(wèn)我,道長(zhǎng)另玖,這世上最難降的妖魔是什么困曙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮谦去,結(jié)果婚禮上慷丽,老公的妹妹穿的比我還像新娘。我一直安慰自己鳄哭,他們只是感情好要糊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著妆丘,像睡著了一般锄俄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勺拣,一...
    開(kāi)封第一講書(shū)人閱讀 50,084評(píng)論 1 291
  • 那天奶赠,我揣著相機(jī)與錄音,去河邊找鬼宣脉。 笑死车柠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的塑猖。 我是一名探鬼主播竹祷,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼羊苟!你這毒婦竟也來(lái)了塑陵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蜡励,失蹤者是張志新(化名)和其女友劉穎令花,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凉倚,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡兼都,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稽寒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扮碧。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慎王,到底是詐尸還是另有隱情蚓土,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布赖淤,位于F島的核電站蜀漆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏咱旱。R本人自食惡果不足惜确丢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望莽龟。 院中可真熱鬧蠕嫁,春花似錦锨天、人聲如沸毯盈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)搂赋。三九已至,卻和暖如春益缠,著一層夾襖步出監(jiān)牢的瞬間脑奠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工幅慌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宋欺,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓胰伍,卻偏偏與公主長(zhǎng)得像齿诞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子骂租,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容