Java集合框架-集合元素的遍历
- 集合元素的遍历操作,使用迭代器Iterator接口
-
Iterator对象称为迭代器(设计模式的一种),主要用于遍历Collection集合中的元素。
-
GOF给迭代器模式的定义为:提供一种方法访问一个容器(container)对象中的各个元素,而又不需要暴露该对象的内部细节。迭代器模式,就是为容器而生。
-
Collection接口继承了java.lang.Iterable接口,改接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了iterator接口的对象
-
package java.lang; import java.util.Iterator; /** Implementing this interface allows an object to be the target of * the "foreach" statement. * @since 1.5 */ public interface Iterable<T> { /** * Returns an iterator over a set of elements of type T. * * @return an Iterator. */ Iterator<T> iterator(); } public interface Collection<E> extends Iterable<E> { /** * Returns an iterator over the elements in this collection. There are no * guarantees concerning the order in which the elements are returned * (unless this collection is an instance of some class that provides a * guarantee). * * @return an <tt>Iterator</tt> over the elements in this collection */ Iterator<E> iterator(); }
-
-
Iterator仅用于遍历集合,Iterator本身并不提供承装对象的能力。如果需要创建Iterator对象,则必须有一个被迭代的集合。
-
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前
- 迭代器Iterator
-
迭代器的抽象方法
-
方法 说明 hasNext() 判断当前节点是否还有子节点,true为有,false为没有 next() 返回迭代器中的下一个元素
-
-
在调用iterator.next()方法之前必须调用iterator.hasNext()进行检测。若不调用,且下一条无记录,直接调用iterator.next()则会抛出异常NoSuchElementException()
-
迭代器的使用:
-
package com.jl.java.base.collection; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * @author jiangl * @version 1.0 * @date 2021/4/22 10:27 */ public class IteratorTest { @Test public void test1(){ Collection collection = new ArrayList(); collection.add(1); collection.add("dfadfas"); collection.add(false); collection.add(new String("fdasdf")); Iterator iterator = collection.iterator(); System.out.println(iterator.next()); System.out.println(iterator.next()); System.out.println(iterator.next()); System.out.println(iterator.next()); //报异常:NoSuchElementException // System.out.println(iterator.next()); Iterator iterator1 = collection.iterator(); for(;iterator1.hasNext();){ System.out.println(iterator1.next()); } Iterator iterator2 = collection.iterator(); while(iterator2.hasNext()){ System.out.println(iterator2.next()); } } }
-
- 迭代器执行原理
- 如图:
- 迭代器的错误使用
-
例子:
-
//二次下移 Iterator iterator3 = collection.iterator(); while(iterator3.next() != null){ System.out.println(iterator3.next()); } //每次都会创建新的迭代器 while(collection.iterator().hasNext()){ System.out.println(collection.iterator().next()); }
-
- 迭代器的remove()方法
-
Iterator内部定义了一个remove()方法,可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove()。(此方法有线程安全问题,会触发fast-fail机制)
-
注意:
- Iterator可以删除集合中的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法
- 如果还未调用next()或在一次次调用next方法之后已经调用了remove方法,再调用remove都会报错IllegalStateException
-
@Test public void test4(){ Collection collection = new ArrayList(); collection.add(1); collection.add("dfadfas"); collection.add(false); collection.add(new String("fdasdf")); System.out.println(collection); Iterator iterator = collection.iterator(); while(iterator.hasNext()){ if(iterator.next().equals("dfadfas")){ iterator.remove(); } } System.out.println(collection); }
- 使用foreach(增强for循环)循环遍历集合
-
Java5.0提供了foreach循环迭代方法Collection和数组
-
遍历操作不需要获取Collection或数组的长度,无需使用索引访问元素。
-
遍历集合的底层调用Iterator完成操作
-
foreach还可以用来遍历数组
-
使用方法: for(集合或数组元素的类型 局部变量 : 集合或数组对象)
-
@Test public void test5(){ Collection collection = new ArrayList(); collection.add(1); collection.add("dfadfas"); collection.add(false); collection.add(new String("fdasdf")); System.out.println(collection); //for(数组元素的类型 局部变量 : 集合对象) for (Object o: collection){ System.out.println(collection); } }
-
编译后:(仍使用的是迭代器)
-
@Test public void test5() { Collection collection = new ArrayList(); collection.add(1); collection.add("dfadfas"); collection.add(false); collection.add(new String("fdasdf")); System.out.println(collection); Iterator i$ = collection.iterator(); while(i$.hasNext()) { Object o = i$.next(); System.out.println(collection); } }
-
-
-
增强for需要注意的问题:
-
在foreach中,对局部变量进行赋值,不会改变原集合或数组对象内的元素内容。因为foreach是将元素取出传递给了局部变量。
-
测试代码:
-
@Test public void test6(){ Collection<MyObject> collection = new ArrayList(); collection.add(new MyObject("123",1)); collection.add(new MyObject("1223",1)); collection.add(new MyObject("1223",1)); System.out.println(collection); for (MyObject o: collection){ o = new MyObject("1",1); } System.out.println(collection); } class MyObject{ private String name; private int age; public MyObject(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "MyObject{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
结果:
- [MyObject{name=‘123’, age=1}, MyObject{name=‘1223’, age=1}, MyObject{name=‘1223’, age=1}]
[MyObject{name=‘123’, age=1}, MyObject{name=‘1223’, age=1}, MyObject{name=‘1223’, age=1}]
- [MyObject{name=‘123’, age=1}, MyObject{name=‘1223’, age=1}, MyObject{name=‘1223’, age=1}]
-
从编译后的class文件看:
-
@Test public void test6() { Collection<MyObject> collection = new ArrayList(); collection.add(new MyObject("123", 1)); collection.add(new MyObject("1223", 1)); collection.add(new MyObject("1223", 1)); System.out.println(collection); Iterator i$ = collection.iterator(); while(i$.hasNext()) { MyObject o = (MyObject)i$.next(); new MyObject("1", 1); } System.out.println(collection); }
-
foreach步骤是先将iterator.next()对象取出,赋值给MyObject o
-
在创建了一个新对象new MyObject(“1”,1)
-
并没有修改原集合中的内容
-
-