HashMapのソースコードを深く掘り下げます。6.5 hashMapの内部のクラス分割ディズエターHashMapSpliter、KeySpliter、Value Splitert、EntrySplitera

7995 ワード

HashMapのソースコードを深く掘り下げます。6.5 hashMapの内部のクラス分割ディズエターHashMapSpliter、KeySpliter、Value Splitert、EntrySplitera
2018年10月1日18:30:57 成熟した黄小天になろうと努力します。 読書数:251
 著作権声明:本文はブロガーのオリジナル文章で、ブロガーの許可なしに転載してはいけません。https://blog.csdn.net/ocp114/article/details/82917933
まず役割を説明します。もとのHashMapにはもうディズマリーがありましたが、なぜこれらのディレクタが必要ですか?愛ですか?責任ですか?(づ。◕‿◕。)づ
ハハハ、李白は存在は合理的だと言いました。
時代の変化に対応するために、並列計算がますます必要になってきました。このローズマリーの誕生も並行反復のために現れました。マルチスレッドの場合は同じHashMapを繰り返してもいいです。しかし、公式はスレッドは一つのローズマリーとしか併用しないと提案しています。
はい、本題に入ります。ここではKeySpliter、Value Splitert、EntrySpliteraは全部Hash MapSpliterに継承されています。ここではKeySpliterとHashMapSpliterのソース解析だけです。他の二つの原理は同じです。いくつかの問題はご覧ください。
static class HashMapSpliterator {
    //       HashMap   
    final HashMap map;
    //          
    Node current;          // current node
    //              
    int index;                  // current index, modified on advance/split
    //              
    int fence;                  // one past last index
    //          ,              
    int est;                    // size estimate
    //      ,        ,          HashMap     ,
    //           expectedModCount   HashMap   modCount      ,         ,  “    ”
    int expectedModCount;       // for comodification checks

    //    
    HashMapSpliterator(HashMap m, int origin, int fence, int est, int expectedModCount) { 
        this.map = m;
        this.index = origin;
        this.fence = fence;
        this.est = est;
        this.expectedModCount = expectedModCount;
    }

    //     ?   ,                        ,        4,             
    //    table      ,             
    final int getFence() { // initialize fence and size on first use
        int hi;
        //               if     
        if ((hi = fence) < 0) {
            HashMap m = map;
            est = m.size;
            expectedModCount = m.modCount;
            Node[] tab = m.table;
            hi = fence = (tab == null) ? 0 : tab.length;
        }
        return hi;
    }

    //                 
    public final long estimateSize() { 
        getFence(); // force init
        return (long) est;
    }
}

static final class KeySpliterator extends HashMapSpliterator implements Spliterator {
    KeySpliterator(HashMap m, int origin, int fence, int est, int expectedModCount) {
        super(m, origin, fence, est, expectedModCount); 
    }

    //           
    public KeySpliterator trySplit() { 
        //                               
        int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
        //           est        ~
        return (lo >= mid || current != null) ? null : 
            new KeySpliterator<>(map, lo, index = mid, est >>>= 1, expectedModCount);
    }

    //               
    public void forEachRemaining(Consumer super K> action) { 
        int i, hi, mc;
        if (action == null)
            throw new NullPointerException();
        HashMap m = map;
        Node[] tab = m.table;
        if ((hi = fence) < 0) {
            mc = expectedModCount = m.modCount;
            hi = fence = (tab == null) ? 0 : tab.length;
        }
        else
            mc = expectedModCount;
        if (tab != null && tab.length >= hi &&
            (i = index) >= 0 && (i < (index = hi) || current != null)) {
            Node p = current;
            current = null;
            do {
                if (p == null)
                    p = tab[i++];
                else {
                    action.accept(p.key);
                    p = p.next;
                }
            } while (p != null || i < hi);
            if (m.modCount != mc)
                throw new ConcurrentModificationException();
        }
    }

    //                 ,                   
    public boolean tryAdvance(Consumer super K> action) { 
        int hi;
        if (action == null)
            throw new NullPointerException();
        Node[] tab = map.table;
        if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
            while (current != null || index < hi) {
                if (current == null)
                    current = tab[index++];
                else {
                    K k = current.key;
                    current = current.next;
                    action.accept(k);
                    if (map.modCount != expectedModCount)
                        throw new ConcurrentModificationException();
                    return true;
                }
            }
        }
        return false;
    }
    
    //     ,         ,              ,           ,
    //          ?              ?      ,    ~
    public int characteristics() { 
        return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) | Spliterator.DISTINCT;
    }
}
  • 1
  • ,
  • 4
  • 5
  • ,
  • ,
  • 8
  • 9,
  • 10
  • 11
  • 15
  • ,
  • ,
  • ,
  • ,
  • ,
  • 23
  • ,
  • ,
  • 30,
  • 31
  • ,
  • 34,
  • ,
  • ,
  • ,
  • 38,
  • 40,
  • ,
  • ,
  • ,
  • ,
  • 46
  • ,
  • 49,
  • 50
  • ,
  • 53,
  • ,
  • ,
  • 59,
  • 60
  • 61,
  • ,
  • ,
  • 64
  • 65,
  • ,
  • ,
  • 69
  • ,
  • 71,
  • ,
  • ,
  • 76
  • ,
  • ,
  • ,
  • 84
  • ,
  • ,
  • ,
  • ,
  • 89,
  • 90,
  • 91
  • 92,
  • ,
  • 94,
  • 95,
  • ,
  • ,
  • ,
  • 100
  • 101,
  • 102
  • 103
  • 104,
  • 105
  • 106,
  • 107,
  • 108
  • 109
  • 110,
  • 111,
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118,
  • 119
  • テストコード
        static class MyThread implements Runnable {
            Spliterator spliterator;
            String threadName;
            
            MyThread(Spliterator spliterator, String threadName) {
                this.spliterator = spliterator;
                this.threadName = threadName;
            }
            @Override
            public void run() {
                spliterator.forEachRemaining(s -> {
                    System.out.println(threadName + "=" + s);
                });
            }
        }
        public static void main(String[] args) {
            HashMap map = new HashMap<>();
            for (int i = 0; i < 23; i++) {
                map.put(i, i);
            }
            Spliterator s1 = map.keySet().spliterator();
            Spliterator s2 = s1.trySplit();
            Spliterator s3 = s2.trySplit();
            
            Thread t1 = new Thread(new MyThread(s1, "  1"));
            Thread t2 = new Thread(new MyThread(s2, "  2"));
            Thread t3 = new Thread(new MyThread(s3, "  3"));
            t1.start();
            t2.start();
            t3.start();
        }
    
  • 1
  • ,
  • 4
  • 5
  • ,
  • ,
  • 8
  • 9,
  • 10
  • 11
  • 15
  • ,
  • ,
  • ,
  • ,
  • ,
  • 23
  • ,
  • ,
  • 30,
  • 31
  • 出力結果
    スレッド2=8スレッド2=9スレッド2=10スレッド2=11スレッド2=12スレッド2=13スレッド2=14スレッド1=16スレッド2=15スレッド3=0スレッド1=17スレッド1=19スレッド1=20スレッド1=21スレッド3=2スレッド3=4スレッド3=5スレッド3=6スレッド3=6スレッド3=7=7