近期在学习队列相关的一些知识,在学习过程中发现Iterable<T>接口中新增了两个新的方法,出于好奇,就想知道这是什么东东,干什么用的。俗话说:实践出真知,所以就有了以下反复的测试。
先看下新增的这两个方法:
1 default void forEach(Consumer<? super T> action) { 2 Objects.requireNonNull(action); 3 for (T t : this) { 4 action.accept(t); 5 } 6 }
1 default Spliterator<T> spliterator() { 2 return Spliterators.spliteratorUnknownSize(iterator(), 0); 3 }
都知道接口中是不能写实现方法的哈,但是它这却有了实现方法,忽然间觉得世界观都被颠覆了,其实呢这也是java8新增的一个特性,在接口方法中添加default关键字就可以直接在接口中写实现(这不是本文的重点,感兴趣的童鞋可以自行学习java8)。
下面正式开始测试<使用BlockingQueue测试>:
1 BlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(1024); 2 while(q.size()<10){ 3 q.put(q.size()+1); 4 } 5 Spliterator<Integer> split = q.spliterator(); 6 split.forEachRemaining(line->{System.out.println(line);}); //①7 System.out.println("-------------------------------------");8 split.forEachRemaining(line->{System.out.println(line);}); //②
以上输出结果为:
1
2
3
4
5
6
7
8
9
10
-------------------------------------
根据以上结果可以看出,②处并没有输出任何的数据。看下Spliterator提供的迭代类forEachRemaining,它是为了并行处理流而新增的一个迭代类,
源码:
1 default void forEachRemaining(Consumer<? super T> action) { 2 do { } while (tryAdvance(action)); 3 }
而tryAdvance
方法则对下一个为处理的操作执行action并返回true, 如果没有下一个元素,返回false。
1 public boolean tryAdvance(Consumer<? super T> action) { 2 if (action == null) throw new NullPointerException(); 3 if (it == null) { 4 it = collection.iterator(); 5 est = (long) collection.size(); 6 } 7 if (it.hasNext()) { 8 action.accept(it.next()); 9 return true; 10 } 11 return false; 12 }
根据上面的源码可以看出,action如果为空直接抛出异常。it为空时,it是遍历传入集合的Iterator对象。
所以在①处:调用了迭代调用了tryAdvance,执行完①之后,it已经指向了conllection的最后一项,而对于②处,传入的集合是同一个集合,对于it也已经指向了最后一项,所以返回了false,没有数据可输出。
trySplit:ArrayListSpliterator的trySplit采用二分法,将前一半数据返回, 如果数据太小不能分了,返回null。而ConcurrentLinkedQueue和ConcurrentLinkedDeque的相应的Spliterator处理稍微复杂一点, 第一次取一个,第二个取两个,不超过MAX_BATCH。
更多的功能还需要慢慢的学习。