集合 Iterator 迭代器 API 案例
Posted baiqiantao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了集合 Iterator 迭代器 API 案例相关的知识,希望对你有一定的参考价值。
接口 Iterable<E>
public interface java.lang.Iterable<T>
1
1
1
public interface java.lang.Iterable<T>
所有已知子接口:BeanContext, BeanContextServices, BlockingDeque<E>, BlockingQueue<E>, Collection<E>, Deque<E>, List<E>, NavigableSet<E>, Queue<E>, Set<E>, SortedSet<E>
实现这个接口允许对象成为 "foreach" 语句的目标。
注意:此接口是定义在 java.lang 包中的,而集合框架中的成员基本都定义在 java.util 包下,所以他也不是 Java Collections Framework 的成员。
定义的方法:
- Iterator<T> iterator() 返回一个在一组 T 类型的元素上进行迭代的迭代器。
接口 Iterator<E>
public interface Iterator<E>
1
1
1
public interface Iterator<E>
对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。迭代器与枚举有两点不同:
- 迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。
- 方法名称得到了改进。
此接口是 Java Collections Framework 的成员。
定义的方法:
- boolean hasNext() 如果仍有元素可以迭代,则返回 true。换句话说,如果 next 返回了元素而不是抛出异常,则返回 true。
- E next() 返回迭代的下一个元素。如果没有元素可以迭代,抛出 NoSuchElementException。
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
Iterator<String> iterator = list.iterator();
System.out.println(iterator.hasNext() + " " + iterator.hasNext() + " " + iterator.hasNext() + " " + iterator.hasNext());//true true true true
System.out.println(iterator.next() + " " + iterator.next() + " " + iterator.next());//a b c
System.out.println(iterator.hasNext()); //false
System.out.println(iterator.next()); //NoSuchElementException
8
8
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
2
Iterator<String> iterator = list.iterator();
3
4
System.out.println(iterator.hasNext() + " " + iterator.hasNext() + " " + iterator.hasNext() + " " + iterator.hasNext());//true true true true
5
System.out.println(iterator.next() + " " + iterator.next() + " " + iterator.next());//a b c
6
7
System.out.println(iterator.hasNext()); //false
8
System.out.println(iterator.next()); //NoSuchElementException
- void remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
- 在没调用 next 之前不能调用此方法。每次调用 next 只能调用一次此方法。多次调用 next 方法后也只能调用一次此方法。
- 如果进行迭代时用调用此方法之外的其他方式修改了该迭代器所指向的 collection,则迭代器的行为是不确定的。
- 抛出:
- UnsupportedOperationException - 如果迭代器不支持 remove 操作。
- IllegalStateException - 如果尚未调用 next 方法,或者在上一次调用 next 方法之后已经调用了 remove 方法。
new ArrayList<String>(Arrays.asList("a", "b", "c")).iterator().remove(); //IllegalStateException
1
1
1
new ArrayList<String>(Arrays.asList("a", "b", "c")).iterator().remove(); //IllegalStateException
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
Iterator<String> iterator = list.iterator();
System.out.println(iterator.next());//a
iterator.remove();
System.out.println(list);//[b, c]
iterator.next();
iterator.next();
iterator.remove();
System.out.println(list);//[b],移除的是最后一次调用 next 时返回的元素
iterator.remove();//IllegalStateException。虽然之前调用了两次 next,但仍然只能调用一次 remove 方法
13
13
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
2
Iterator<String> iterator = list.iterator();
3
4
System.out.println(iterator.next());//a
5
iterator.remove();
6
System.out.println(list);//[b, c]
7
8
iterator.next();
9
iterator.next();
10
iterator.remove();
11
System.out.println(list);//[b],移除的是最后一次调用 next 时返回的元素
12
13
iterator.remove();//IllegalStateException。虽然之前调用了两次 next,但仍然只能调用一次 remove 方法
接口 ListIterator<E>
public interface ListIterator<E> extends Iterator<E>
1
1
1
public interface ListIterator<E> extends Iterator<E>
列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator 没有当前元素;它的光标位置 始终位于调用 previous() 所返回的元素和调用 next() 所返回的元素之间。长度为 n 的列表的迭代器有 n+1 个可能的指针位置,如下面的插入符举例说明:
注意,remove() 和 set(Object) 方法不是 根据光标位置定义的,它们是根据对调用 next() 或 previous() 所返回的最后一个元素的操作定义的。
此接口是 Java Collections Framework 的成员。
定义的方法:
1、Iterator<E> 中的方法或类似的方法:
- boolean hasNext/hasPrevious() 以正向遍历列表时,如果列表迭代器有多个元素,则返回 true。换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true。
- E next/previous() 返回列表中的下一个元素。
- 可以重复调用此方法来迭代此列表,或混合调用 previous 来前后移动。
- 注意交替调用 next 和 previous 将重复返回相同的元素。
- 如果没有可迭代的下一个元素,则抛出 NoSuchElementException 。
- void remove() 从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
- 对于每个 next 或 previous 调用,只能执行一次此调用。
- 只有在最后一次调用 next 或 previous 之后,尚未调用 ListIterator.add 时才可以执行该调用。
- 抛出:
- UnsupportedOperationException - 如果列表迭代器不支持 remove 操作。
- IllegalStateException - 既没有调用 next 也没有调用 previous,或者在最后一次调用 next 或 previous 后调用了 remove 或 add。
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
ListIterator<String> iterator = list.listIterator();
System.out.println(iterator.hasPrevious() + " " + iterator.hasNext() + " " + iterator.hasPrevious());//false true false
System.out.println(iterator.next() + " " + iterator.next() + " " + iterator.previous());//a b b,交替调用 next 和 previous 将重复返回相同的元素
iterator.remove();
System.out.println(list);//[a, c]
7
7
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
2
ListIterator<String> iterator = list.listIterator();
3
4
System.out.println(iterator.hasPrevious() + " " + iterator.hasNext() + " " + iterator.hasPrevious());//false true false
5
System.out.println(iterator.next() + " " + iterator.next() + " " + iterator.previous());//a b b,交替调用 next 和 previous 将重复返回相同的元素
6
iterator.remove();
7
System.out.println(list);//[a, c]
2、新增的增强功能的方法:
- void add(E e) 将指定的元素插入列表(可选操作)。
- 该元素直接插入到 next 返回的下一个元素的前面(如果有),或者 previous 返回的下一个元素之后(如果有)
- 如果列表没有元素,那么新元素就成为列表中的唯一元素。
- 新元素被插入到隐式光标前:不影响对 next 的后续调用,并且对 previous 的后续调用会返回此新元素(此调用把调用 nextIndex 或 previousIndex 所返回的值增加 1)。
- 抛出:
- UnsupportedOperationException - 如果列表迭代器不支持 add 操作。
- ClassCastException - 如果指定元素的类不允许该元素添加到此列表。
- IllegalArgumentException - 如果此元素的某个方面不允许该元素添加到此列表。
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
ListIterator<String> iterator = list.listIterator();
iterator.add("add1");//该元素直接插入到 next 返回的下一个元素的前面,而 next返回的下一个元素是 a
//因为 previous 没有元素,所以不能用 previous 的规则去解释
iterator.add("add2");//该元素直接插入到 next 返回的下一个元素的前面,而 next返回的下一个元素是 a
//同时也可以这样解释:该元素直接插入到 previous 返回的下一个元素之后,而 previous 返回的下一个元素是 add1
System.out.println(list);//[add1, add2, a, b, c]
System.out.println(iterator.next()); //a
System.out.println(iterator.previous() + " " + iterator.previous());//a add2
iterator.add("add3");//该元素直接插入到 previous 返回的下一个元素之后,而 previous 返回的下一个元素是 add1
//同时也可以这样解释:该元素直接插入到 next 返回的下一个元素的前面,而 next 返回的下一个元素是 add2
iterator.add("add4");//该元素直接插入到 previous 返回的下一个元素之后,而 previous 返回的下一个元素是刚刚通过 add 添加的元素 add3
//同时也可以这样解释:该元素直接插入到 next 返回的下一个元素的前面,而 next 返回的下一个元素是 add2
System.out.println(list);//[add1, add3, add4, add2, a, b, c]
16
16
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
2
ListIterator<String> iterator = list.listIterator();
3
4
iterator.add("add1");//该元素直接插入到 next 返回的下一个元素的前面,而 next返回的下一个元素是 a
5
//因为 previous 没有元素,所以不能用 previous 的规则去解释
6
iterator.add("add2");//该元素直接插入到 next 返回的下一个元素的前面,而 next返回的下一个元素是 a
7
//同时也可以这样解释:该元素直接插入到 previous 返回的下一个元素之后,而 previous 返回的下一个元素是 add1
8
System.out.println(list);//[add1, add2, a, b, c]
9
10
System.out.println(iterator.next()); //a
11
System.out.println(iterator.previous() + " " + iterator.previous());//a add2
12
iterator.add("add3");//该元素直接插入到 previous 返回的下一个元素之后,而 previous 返回的下一个元素是 add1
13
//同时也可以这样解释:该元素直接插入到 next 返回的下一个元素的前面,而 next 返回的下一个元素是 add2
14
iterator.add("add4");//该元素直接插入到 previous 返回的下一个元素之后,而 previous 返回的下一个元素是刚刚通过 add 添加的元素 add3
15
//同时也可以这样解释:该元素直接插入到 next 返回的下一个元素的前面,而 next 返回的下一个元素是 add2
16
System.out.println(list);//[add1, add3, add4, add2, a, b, c]
- void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
- 只有在最后一次调用 next 或 previous 后既没有调用 ListIterator.remove 也没有调用 ListIterator.add 时才可以进行该调用。
- 参数:e - 用于替换 next 或 previous 返回的最后一个元素的元素。
- 抛出:
- UnsupportedOperationException - 如果列表迭代器不支持 set 操作。
- ClassCastException - 如果指定元素的类不允许该元素添加到此列表。
- IllegalArgumentException - 如果指定元素的某个方面不允许该元素添加到此列表。
- IllegalStateException - 如果既没有调用 next 也没有调用 previous,或者在最后一次调用 next 或 previous 后调用了 remove 或 add。
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
ListIterator<String> iterator = list.listIterator();
iterator.add("add1");
System.out.println(iterator.next() + " " + iterator.next()); //a b
iterator.set("set");
System.out.println(list);//[add1, a, set, c]
7
7
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
2
ListIterator<String> iterator = list.listIterator();
3
4
iterator.add("add1");
5
System.out.println(iterator.next() + " " + iterator.next()); //a b
6
iterator.set("set");
7
System.out.println(list);//[add1, a, set, c]
- int nextIndex() 返回对 next 的后续调用所返回元素的索引。如果列表迭代器在列表的结尾,则返回列表的大小。
- int previousIndex() 返回对 previous 的后续调用所返回元素的索引。如果列表迭代器在列表的开始,则返回 -1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
ListIterator<String> iterator = list.listIterator();
System.out.println(iterator.nextIndex() + " " + iterator.nextIndex() + " " + iterator.previousIndex());//0 0 -1
iterator.add("add1");
System.out.println(iterator.nextIndex() + " " + iterator.previousIndex());//1 0
System.out.println(iterator.next() + " " + list); //a [add1, a, b, c]
System.out.println(iterator.nextIndex() + " " + iterator.previousIndex());//2 1
System.out.println(iterator.previous() + " " + iterator.previous());//a add1
System.out.println(iterator.nextIndex() + " " + iterator.previousIndex());//0 -1
12
12
1
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
2
ListIterator<String> iterator = list.listIterator();
3
4
System.out.println(iterator.nextIndex() + " " + iterator.nextIndex() + " " + iterator.previousIndex());//0 0 -1
5
iterator.add("add1");
6
System.out.println(iterator.nextIndex() + " " + iterator.previousIndex());//1 0
7
8
System.out.println(iterator.next() + " " + list); //a [add1, a, b, c]
9
System.out.println(iterator.nextIndex() + " " + iterator.previousIndex());//2 1
10
11
System.out.println(iterator.previous() + " " + iterator.previous());//a add1
12
System.out.println(iterator.nextIndex() + " " + iterator.previousIndex());//0 -1
示例代码
各种姿势测试 add
1、在集合的最前面按顺序添加若干元素:
List<String> list1 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
ListIterator<String> iterator1 = list1.listIterator();
iterator1.add("D");
iterator1.add("E");
System.out.println(list1);//[D, E, a, b, c]
1
List<String> list1 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
2
ListIterator<String> iterator1 = list1.listIterator();
3
iterator1.add("D");
4
iterator1.add("E");
5
System.out.println(list1);//[D, E, a, b, c]
2、在集合的最后面按顺序添加若干元素:
List<String> list2 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
ListIterator<String> iterator2 = list2.listIterator();
while (iterator2.hasNext()) {
iterator2.next();
}
iterator2.add("D");
iterator2.add("E");
System.out.println(list2);//[a, b, c, D, E]
1
List<String> list2 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
2
ListIterator<String> iterator2 = list2.listIterator();
3
while (iterator2.hasNext()) {
4
iterator2.next();
5
}
6
iterator2.add("D");
7
iterator2.add("E");
8
System.out.println(list2);//[a, b, c, D, E]
3、在集合的每个元素的前面和后面都添加若干元素:
List<String> list3 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
ListIterator<String> iterator3 = list3.listIterator();
while (iterator3.hasNext()) {
String item = list3.get(iterator3.nextIndex());
iterator3.add(item + "前面1");
iterator3.add(item + "前面2");
iterator3.next();
iterator3.add(item + "后面1");
iterator3.add(item + "后面2");
}
System.out.println(list3);//[a前面1, a前面2, a, a后面1, a后面2, b前面1, b前面2, b, b后面1, b后面2, c前面1, c前面2, c, c后面1, c后面2]
10
1
List<String> list3 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
2
ListIterator<String> iterator3 = list3.listIterator();
3
while (iterator3.hasNext()) {
4
String item = list3.get(iterator3.nextIndex());
5
iterator3.add(item + "前面1");
6
iterator3.add(item + "前面2");
7
iterator3.next();
8
iterator3.add(item + "后面1");
9
iterator3.add(item + "后面2");
10
}
11
System.out.println(list3);//[a前面1, a前面2, a, a后面1, a后面2, b前面1, b前面2, b, b后面1, b后面2, c前面1, c前面2, c, c后面1, c后面2]
4、在集合的指定元素的前面和后面添加若干元素:
List<String> list4 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
ListIterator<String> iterator4 = list4.listIterator();
while (iterator4.hasNext()) {
String item = iterator4.next();
if (item.equals("a") || item.equals("c")) {
iterator4.previous();//先重新指向 item 的前面,这里不用担心 NoSuchElementException
iterator4.add(item + "前面1");//在前面添加元素,添加后还是指向的 item 的前面
iterator4.add(item + "前面2");//在前面添加元素,添加后还是指向的 item 的前面
iterator4.next();//向后【再】移动一位,现在指向的是 item 的后面
iterator4.add(item + "后面1");//在 item 的后面添加元素
iterator4.add(item + "后面2");//在 item 的后面添加元素
}
}
System.out.println(list4);//[a前面1, a前面2, a, a后面1, a后面2, b, c前面1, c前面2, c, c后面1, c后面2]
14
1
List<String> list4 = new ArrayList<>(Arrays.asList(new String[] { "a", "b", "c" }));
2
ListIterator<String> iterator4 = list4.listIterator();
3
while (iterator4.hasNext()) {
4
String item = iterator4.next();
5
if (item.equals("a") || item.equals("c")) {
6
iterator4.previous();//先重新指向 item 的前面,这里不用担心 NoSuchElementException
7
iterator4.add(item + "前面1");//在前面添加元素,添加后还是指向的 item 的前面
8
iterator4.add(item + "前面2");//在前面添加元素,添加后还是指向的 item 的前面
9
iterator4.next();//向后【再】移动一位,现在指向的是 item 的后面
10
iterator4.add(item + "后面1");//在 item 的后面添加元素
11
iterator4.add(item + "后面2");//在 item 的后面添加元素
12
}
13
}
14
System.out.println(list4);//[a前面1, a前面2, a, a后面1, a后面2, b, c前面1, c前面2, c, c后面1, c后面2]
各种姿势测试 remove
可以随意 add,但 remove 必须要跟在 next() 或是 previous() 之后,而且只能执行一次。
1、替换指定元素
List<String> list1 = new ArrayList<String>(Arrays.asList(new String[] { "a", "b", "c", "b" }));
ListIterator<String> iterator1 = list1.listIterator();
while (iterator1.hasNext()) {
if (iterator1.next().equals("b")) {
iterator1.remove();
iterator1.add("替换");
}
}
System.out.println(list1);//[a, 替换, c, 替换]
1
List<String> list1 = new ArrayList<String>(Arrays.asList(new String[] { "a", "b", "c", "b" }));
2
ListIterator<String> iterator1 = list1.listIterator();
3
while (iterator1.hasNext()) {
4
if (iterator1.next().equals("b")) {
5
iterator1.remove();
6
iterator1.add("替换");
7
}
8
}
9
System.out.println(list1);//[a, 替换, c, 替换]
2、移除某个元素及其前后的元素
List<String> list2 = new ArrayList<String>(Arrays.asList(new String[] { "a1", "a2", "a3", "b", "c1", "c2", "c3" }));
ListIterator<String> iterator2 = list2.listIterator();
while (iterator2.hasNext()) {
String item = iterator2.next();
if (item.equals("b")) {
System.out.println("当前元素 " + item);
iterator2.remove(); //移除当前元素
if (iterator2.hasPrevious()) {
System.out.println("前 1 个元素 " + iterator2.previous()); //移除此元素的前 1 个元素
iterator2.remove();
}
if (iterator2.hasPrevious()) {
System.out.println("前 2 个元素 " + iterator2.previous()); //移除此元素的前 2 个元素
iterator2.remove();
}
if (iterator2.hasNext()) {
System.out.println("后 1 个元素 " + iterator2.next()); //移除此元素的后 1 个元素
iterator2.remove();
}
if (iterator2.hasNext()) {
System.out.println("后 2 个元素 " + iterator2.next()); //移除此元素的后 2 个元素
iterator2.remove();
}
}
}
System.out.println(list2);//[a1, c3]
//如果 item 为 a1 ,结果为 [b, c1, c2, c3]
//如果 item 为 a2 ,结果为 [c1, c2, c3]
//如果 item 为 c2 ,结果为 [a1, a2, a3]
x
1
List<String> list2 = new ArrayList<String>(Arrays.asList(new String[] { "a1", "a2", "a3", "b", "c1", "c2", "c3" }));
2
ListIterator<String> iterator2 = list2.listIterator();
3
while (iterator2.hasNext()) {
4
String item = iterator2.next();
5
if (item.equals("b")) {
6
System.out.println("当前元素 " + item);
7
iterator2.remove(); //移除当前元素
8
if (iterator2.hasPrevious()) {
9
System.out.println("前 1 个元素 " + iterator2.previous()); //移除此元素的前 1 个元素
10
iterator2.remove();
11
}
12
if (iterator2.hasPrevious()) {
13
System.out.println("前 2 个元素 " + iterator2.previous()); //移除此元素的前 2 个元素
14
iterator2.remove();
15
}
16
if (iterator2.hasNext()) {
17
System.out.println("后 1 个元素 " + iterator2.next()); //移除此元素的后 1 个元素
18
iterator2.remove();
19
}
20
if (iterator2.hasNext()) {
21
System.out.println("后 2 个元素 " + iterator2.next()); //移除此元素的后 2 个元素
22
iterator2.remove();
23
}
24
}
25
}
26
System.out.println(list2);//[a1, c3]
27
//如果 item 为 a1 ,结果为 [b, c1, c2, c3]
28
//如果 item 为 a2 ,结果为 [c1, c2, c3]
29
//如果 item 为 c2 ,结果为 [a1, a2, a3]
注意:如果通过这种方式移除时,在遍历过程中如果发现了多个满足条件的 item,请一定要注意,在前一个 item 相关的 remove 操作结束后,整个集合已经改变,所以集合中的元素排列位置也已经改变,所以之前不在一起的元素可能就会因为中间的一些元素被删除掉而在一起了,这是你就要考虑到底是不是你需要的操作。
例如,同样是上面的案例,如果原始集合为
List<String> list2 = new ArrayList<String>(Arrays.asList(new String[] { "a1", "a2", "a3", "b", "c1", "c2", "c3", "b" }));
x
1
List<String> list2 = new ArrayList<String>(Arrays.asList(new String[] { "a1", "a2", "a3", "b", "c1", "c2", "c3", "b" }));
则结果不是你原以为的有一个元素 a1,而是一个空集合了,因为在 remove 最后一个 b 时,第一个元素 a1 也是他的第 "前 2 个元素" 。
3、移除指定范围内的所有元素
List<String> list3 = new ArrayList<String>(Arrays.asList(new String[] { "a", "开始", "b", "c", "d", "结束", "e" }));
ListIterator<String> iterator3 = list3.listIterator();
while (iterator3.hasNext()) {
if (iterator3.next().equals("开始")) {
iterator3.remove();//注释掉这行代码则不移除"开始"
while (iterator3.hasNext()) {
if (!iterator3.next().equals("结束")) {
iterator3.remove();//remove之后必须再调用next方法后才能再remove
} else {
iterator3.remove();//注释掉这行代码则不移除"结束"
break;//结束while循环
}
}
}
}
System.out.println(list3);//[a, e]
16
1
List<String> list3 = new ArrayList<String>(Arrays.asList(new String[] { "a", "开始", "b", "c", "d", "结束", "e" }));
2
ListIterator<String> iterator3 = list3.listIterator();
3
while (iterator3.hasNext()) {
4
if (iterator3.next().equals("开始")) {
5
iterator3.remove();//注释掉这行代码则不移除"开始"
6
while (iterator3.hasNext()) {
7
if (!iterator3.next().equals("结束")) {
8
iterator3.remove();//remove之后必须再调用next方法后才能再remove
9
} else {
10
iterator3.remove();//注释掉这行代码则不移除"结束"
11
break;//结束while循环
12
}
13
}
14
}
15
}
16
System.out.println(list3);//[a, e]
2018-7-14
以上是关于集合 Iterator 迭代器 API 案例的主要内容,如果未能解决你的问题,请参考以下文章
[Design Pattern] Iterator Pattern 简单案例
尚硅谷设计模式学习(17)---[迭代器模式(Iterator Pattern)]
集合foreach迭代时,边迭代边删除,只能使用迭代器删除,不能使用集合删除,否则会导致并发修改异常for-each和Iterator的选择