1.Iterator接口
1.1 Iterator接口和其他集合類的關系
Java集合類中,Iterable接口屬于頂層接口,除Map接口外,其他都實現了Iterable接口,這意味著它們都可以重寫和使用Iterable接口中的方法
1.2 Iterable接口簡介
在JDK1.7以前,Iterable接口內部只定義了iterator()方法。然而在JDK1.8及以后,又新增了forEach()和spliterator()方法
1.2.1 iterator()
作用:iterator()方法用于返回一個Iterator對象,該對象是一個接口,用于遍歷Iterable集合中的元素。Iterator中的方法是實現Iterable遍歷功能的核心方法
(1)boolean hasNext():判斷集合中是否有還有下一個元素
(2)E next():返回集合中的下一個元素
list.iterator()表示返回一個Iterator對象指向list,以下可以看作是遍歷過程
(3)default void remove():移除集合中上一次調用next()返回的元素
remove()方法可以在遍歷過程中調用,這表示遍歷和修改元素的操作可以同步進行
在JDK1.8及以后,Iterator中又新添了
default void forEachRemaining(Consumer<? super E> action)
方法。該方法會按順序對迭代器中的剩余的每個元素進行特定的操作
public static void main(String[] args) {List<Integer> list = new ArrayList<>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);Iterator<Integer> iterator = list.iterator();//重寫Consumer對象中的accept方法,該方法內部可以對遍歷的元素進行執行的操作//lambda表達式iterator.forEachRemaining(integer -> {integer += 1;System.out.println(integer);});
}
1.2.2 forEach()&foreach()
(1)Iterable接口中的forEach()方法實際上和上述forEachRemaining差不多,該方法會按順序對遍歷的每個元素進行特定的操作
我這里forEach方法只是對遍歷的元素進行打印,如果想和上述forEachRemaining一樣,先+1再打印,也是可以做到的
(2)foreach又叫做增強型for循環,是一種語法糖,就是一種語法形式(規定吧)。它在內部實際上使用了Iterator來實現遍歷,調用iterator()方法來獲取迭代器,然后使用hasNext()和next()來遍歷集合
foreach和迭代器的區別?
答:迭代器可以在遍歷過程中使用remove()方法來刪除元素,并且該刪除操作是可以映射到集合本身的;但是foreach方法不行
1.2.3 spliterator()方法
作用:用于返回Spliterator對象,該對象是一個接口,用于遍歷Iterable集合中的元素。和Iterator對象最大的區別是,使用Spliterator對象中的方法來遍歷集合支持并行處理,這在多線程環境下性能高于使用Iterator來遍歷(但是Spliterator不能保證線程安全性)
(1)boolean tryAdvance(Consumer<? super T>
action):處理當前元素,并移動到下一個元素(類似Iterator中的next方法) (2)Spliterator
trySplit():將當前需要遍歷的集合拆分為兩個部分,返回一個新的Spliterator對象用于處理前半部分,剩下一般由原Spliterator處理
以ArrayList為例:
public class ArrayListParallelSpliteratorExample {public static void main(String[] args) {// 創建一個包含整數的 ArrayListList<Integer> numbers = new ArrayList<>();for (int i = 1; i <= 20; i++) {numbers.add(i);}// 獲取 ArrayList 的 spliteratorOneSpliterator<Integer> spliteratorOne = numbers.spliterator();// 使用 trySplit() 方法拆分 spliteratorTwoSpliterator<Integer> spliteratorTwo = spliteratorOne.trySplit();// 定義一個處理元素的 Consumerjava.util.function.Consumer<Integer> action = (Integer number) ->System.out.println("當前線程: " + Thread.currentThread().getName() + " 處理數字: " + number);// 使用第一個 Spliterator 進行遍歷/*System.out.println("使用第一個 Spliterator 進行遍歷:");spliteratorOne.forEachRemaining(action);// 使用拆分后的 Spliterator 進行遍歷System.out.println("\n使用拆分后的 Spliterator 進行遍歷:");if (spliteratorTwo != null) {spliteratorTwo.forEachRemaining(action);}*///ThreadPoolExecutor executor = new ThreadPoolExecutor(2,2,0,TimeUnit.MINUTES,new ArrayBlockingQueue<>(1),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 2; i++) {executor.execute(() -> {spliteratorOne.forEachRemaining(action);spliteratorTwo.forEachRemaining(action);});}}
}
運行結果: