makotan _at_ gmail dot com

Collectionに追加しながらStreamで処理するとどうなるのか?確認してみた

Streamを使いつつふと思った疑問点が解消するかなぁ〜と


試したコード

        final AtomicInteger ai = new AtomicInteger(1);
        final ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
        Streams.intRange(1,6).forEach((i)-> {
            queue.add(ai.getAndIncrement());
            System.out.print(" "+i);
        });

        System.out.println(" ");
        System.out.println("start:"+queue.size());
        System.out.println("");

        final long count = queue.stream()
                .peek((i) -> System.out.println("CHECK:" + i))
                .map((v) -> {
                    if ((v % 2) == 1) {
                        final int i = ai.getAndIncrement();
                        queue.add(i);
                        System.out.println("ADD:"+i);
                    }
                    return v;
                })
                .filter((v) -> (v % 2) == 0)
                .peek((i) -> System.out.println("OK:" + i))
                .count();

        System.out.println("");
        System.out.println("total:"+count);

簡単に説明するとConcurrentLinkedQueueに初期値を設定した後に、Streamの処理中に半分の確率で値を挿入していって、合計何個の値が返ってくるのか?
って言うのを確認するテスト
理想的には初期設定の数と結果の数は同じになって欲しいんだけど・・・



結果は・・・

 1 2 3 4 5 
start:5

CHECK:1
ADD:6
CHECK:2
OK:2
CHECK:3
ADD:7
CHECK:4
OK:4
CHECK:5
ADD:8
CHECK:6
OK:6
CHECK:7
ADD:9
CHECK:8
OK:8
CHECK:9
ADD:10

total:4

開始時の数が5で終了時の数が4で一個少ない(>_<)
確認のために開始の数を6にしてみたりしたけど、やっぱり一個だけ少なくなる
ConcurrentLinkedQueueのStreamの実装を見てたらそうなるよなぁ〜って思ったので理由が気になる人はソースコードをどうぞ。
そんなわけでクラスによって違う動きをする事もあるんじゃ無いかなってちょっと思った。
普通のArrayListだとIteratorでぶん回してたのと同じ結果だったしw