目录
1. 关于集合框架
1.1 集合接口
1.2 集合实现类
1.3 集合算法及迭代器和比较器的使用
2. 数据结构
2.1 ArrayList
2.2 LinkedList
2.3 HashMap
2.4 HashSet
3. 迭代器
1. 关于集合框架
集合框架是使用数据结构(参见本文2. 数据结构)来满足一组标准接口的设计。集合框架提供了一套性能优良,使用方便的接口和类,java集合框架位于java.util包中, 所以当使用集合框架的时候需要进行导包。
集合框架被设计成要满足以下几个目标:
- 该框架必须是高性能的。基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。
- 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。
- 对一个集合的扩展和适应必须是简单的。
所有的集合框架都包含如下内容:
- 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
- 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
- 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序,这些算法实现了多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
集合框架体系图
1.1 集合接口
接口 | 描述 |
Collection接口 | Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。 Collection 接口存储一组不唯一,无序的对象。 |
List接口 | List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。 List 接口存储一组不唯一,有序(插入顺序)的对象。 |
Set | Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。 Set 接口存储一组唯一,无序的对象。 |
SortedSet | 继承于Set保存有序的集合。 |
Map | Map 接口存储一组键值对象,提供key(键)到value(值)的映射。 |
Map.Entry | 描述在一个Map中的一个元素(键/值对)。是一个 Map 的内部接口。 |
SortedMap | 继承于 Map,使 Key 保持在升序排列。 |
Enumeration | 这是一个传统的接口和定义的方法,通过它可以枚举(一次获得一个)对象集合中的元素。这个传统接口已被迭代器取代。 |
1.2 集合实现类
标准集合类
类 | 描述 |
AbstractCollection | 实现了大部分的集合接口。 |
AbstractList | 继承于AbstractCollection 并且实现了大部分List接口。 |
AbstractSequentialList | 继承于 AbstractList ,提供了对数据元素的链式访问而不是随机访问。 |
LinkedList | 该类实现了List接口,允许有null(空)元素。主要用于创建链表数据结构,该类没有同步方法,如果多个线程同时访问一个List,则必须自己实现访问同步,解决方法就是在创建List时候构造一个同步的List。例如: List list=Collections.synchronizedList(newLinkedList(...)); LinkedList 查找效率低。 |
ArrayList | 该类也是实现了List的接口,实现了可变大小的数组,随机访问和遍历元素时,提供更好的性能。该类也是非同步的,在多线程的情况下不要使用。ArrayList 增长当前长度的50%,插入删除效率低。 |
AbstractSet | 继承于AbstractCollection 并且实现了大部分Set接口。 |
HashSet | 该类实现了Set接口,不允许出现重复元素,不保证集合中元素的顺序,允许包含值为null的元素,但最多只能一个。 |
LinkedHashSet | 具有可预知迭代顺序的Set接口的哈希表和链接列表实现。 |
TreeSet | 该类实现了Set接口,可以实现排序等功能。 |
AbstractMap | 实现了大部分的Map接口。 |
HashMap | HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 |
TreeMap | 继承了AbstractMap,并且使用一颗树。 |
WeakHashMap | 继承AbstractMap类,使用弱密钥的哈希表。 |
LinkedHashMap | 继承于HashMap,使用元素的自然顺序对元素进行排序. |
IdentityHashMap | 继承AbstractMap类,比较文档时使用引用相等。 |
其他集合类
类 | 描述 |
Vector | 该类和ArrayList非常相似,但是该类是同步的,可以用在多线程的情况,该类允许设置默认的增长长度,默认扩容方式为原来的2倍。 |
Stack | 栈是Vector的一个子类,它实现了一个标准的后进先出的栈。 |
Dictionary | Dictionary 类是一个抽象类,用来存储键/值对,作用和Map类相似。 |
Hashtable | Hashtable 是 Dictionary(字典) 类的子类,位于 java.util 包中。 |
Properties | Properties 继承于 Hashtable,表示一个持久的属性集,属性列表中每个键及其对应值都是一个字符串。 |
BitSet | 一个Bitset类创建一种特殊类型的数组来保存位值。BitSet中数组大小会随需要增加。 |
1.3 集合算法及迭代器和比较器的使用
集合算法
Collection Algorithms:这里是一个列表中的所有算法实现。
集合框架定义了几种算法,可用于集合和映射。这些算法被定义为集合类的静态方法。
在尝试比较不兼容的类型时,一些方法能够抛出 ClassCastException异常。当试图修改一个不可修改的集合时,抛出UnsupportedOperationException异常。
集合定义三个静态的变量:EMPTY_SET,EMPTY_LIST,EMPTY_MAP的。这些变量都不可改变。
迭代器(Iterator )的使用
通常情况下,你会希望遍历一个集合中的元素。例如,显示集合中的每个元素。
一般遍历数组都是采用for循环或者增强for,这两个方法也可以用在集合框架,但是还有一种方法是采用迭代器遍历集合框架,它是一个对象,实现了Iterator 接口或 ListIterator接口。
迭代器,使你能够通过循环来得到或删除集合的元素。ListIterator 继承了 Iterator,以允许双向遍历列表和修改元素。
比较器(Comparator)的使用
TreeSet和TreeMap的按照排序顺序来存储元素. 然而,这是通过比较器来精确定义按照什么样的排序顺序。
这个接口可以让我们以不同的方式来排序一个集合。
2. 数据结构
java.util 包中提供了许多数据结构的实现,可以根据需要选择合适的类。
常见数据结构
数据结构 | 特点 | 优点 | 缺点 | 说明 | 实例 |
数组(Arrays) | 固定大小,存储相同类型的元素 | 随机访问元素效率高 | 大小固定,插入和删除元素相对较慢 | 一种基本的数据结构,可以存储固定大小的相同类型的元素。 | int[] array = new int[5]; |
列表(Lists)—ArrayList | 动态数组,可变大小 | 高效的随机访问和快速尾部插入 | 中间插入和删除相对较慢 | List<String> arrayList = new ArrayList<>(); | |
列表(Lists)—LinkedList | 双向链表,元素之间通过指针连接 | 插入和删除元素高效,迭代器性能好 | 随机访问相对较慢 | List<Integer> linkedList = new LinkedList<>(); | |
集合(Sets)—HashSet | 无序集合,基于HashMap实现 | 高效的查找和插入操作 | 不保证顺序 | 用于存储不重复的元素 | Set<String> hashSet = new HashSet<>(); |
集合(Sets)—TreeSet | 是有序集合,底层基于红黑树实现,不允许重复元素 | 提供自动排序功能,适用于需要按顺序存储元素的场景 | 性能相对较差,不允许插入 null 元素 | 用于存储不重复的元素 | Set<Integer> treeSet = new TreeSet<>(); |
映射(Maps)—HashMap | 基于哈希表实现的键值对存储结构 | 高效的查找、插入和删除操作 | 无序,不保证顺序 | 用于存储键值对 | Map<String, Integer> hashMap = new HashMap<>(); |
映射(Maps)—TreeMap | 基于红黑树实现的有序键值对存储结构 | 有序,支持按照键的顺序遍历 | 插入和删除相对较慢 | 用于存储键值对 | Map<String, Integer> treeMap = new TreeMap<>(); |
栈(Stack) | 代表一个栈,通常按照后进先出(LIFO)的顺序操作元素 | 新元素被添加到栈的顶部,而只能从栈的顶部移除元素。最后添加的元素是第一个被移除的。 | 是一种线性数据结构,它按照后进先出(Last In, First Out,LIFO)的原则管理元素 | Stack<Integer> stack = new Stack<>(); | |
队列(Queue) | 代表一个队列,通常按照先进先出(FIFO)的顺序操作元素 | 遵循先进先出(FIFO)原则,常见的实现有 LinkedList 和 PriorityQueue | Queue<String> queue = new LinkedList<>(); | ||
堆(Heap) | 优先队列的基础,可以实现最大堆和最小堆 | PriorityQueue<Integer> minHeap = new PriorityQueue<>(); PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder()); | |||
树(Trees) | TreeNode 类型,可以用于构建二叉树等数据结构 | class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int x) { val = x; } } | |||
图(Graphs) | 图的表示通常需要自定义数据结构或使用图库,Java 没有内建的图类 |
其他数据结构
数据结构 | 说明 |
枚举(Enumeration) | 枚举(Enumeration)接口虽然它本身不属于数据结构,但它在其他数据结构的范畴里应用很广。 枚举(The Enumeration)接口定义了一种从数据结构中取回连续元素的方式 |
位集合(BitSet) | 位集合类实现了一组可以单独设置和清除的位或标志。该类在处理一组布尔值的时候非常有用,你只需要给每个值赋值一"位",然后对位进行适当的设置或清除,就可以对布尔值进行操作了。 |
向量(Vector) | 向量(Vector)类和传统数组非常相似,但是Vector的大小能根据需要动态的变化。 和数组一样,Vector对象的元素也能通过索引访问。 使用Vector类最主要的好处就是在创建对象的时候不必给对象指定大小,它的大小会根据需要动态的变化 |
栈(Stack) | 栈(Stack)实现了一个后进先出(LIFO)的数据结构。 你可以把栈理解为对象的垂直分布的栈,当你添加一个新元素时,就将新元素放在其他元素的顶部。 当你从栈中取元素的时候,就从栈顶取一个元素。换句话说,最后进栈的元素最先被取出。 |
字典(Dictionary) | 字典(Dictionary) 类是一个抽象类,它定义了键映射到值的数据结构。 当你想要通过特定的键而不是整数索引来访问数据的时候,这时候应该使用 Dictionary。 由于 Dictionary 类是抽象类,所以它只提供了键映射到值的数据结构,而没有提供特定的实现。 Dictionary 类在较新的 Java 版本中已经被弃用(deprecated),推荐使用 Map 接口及其实现类,如 HashMap、TreeMap 等,来代替 Dictionary。 |
哈希表(Hashtable) | Hashtable类提供了一种在用户定义键结构的基础上来组织数据的手段。 例如,在地址列表的哈希表中,你可以根据邮政编码作为键来存储和排序数据,而不是通过人名。 哈希表键的具体含义完全取决于哈希表的使用情景和它包含的数据。 |
属性(Properties) | Properties 继承于 Hashtable.Properties 类表示了一个持久的属性集.属性列表中每个键及其对应值都是一个字符串。 Properties 类被许多Java类使用。例如,在获取环境变量时它就作为System.getProperties()方法的返回值。 |
2.1 ArrayList
ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。
ArrayList 继承了 AbstractList ,并实现了 List 接口。
使用 ArrayList的情况 :
- 频繁访问列表中的某一个元素。
- 只需要在列表末尾进行添加和删除元素操作。
常用方法
方法 | 描述 |
add() | 将元素插入到指定位置的 arraylist 中 |
addAll() | 添加集合中的所有元素到 arraylist 中 |
clear() | 删除 arraylist 中的所有元素 |
clone() | 复制一份 arraylist |
contains() | 判断元素是否在 arraylist |
get() | 通过索引值获取 arraylist 中的元素 |
indexOf() | 返回 arraylist 中元素的索引值 |
removeAll() | 删除存在于指定集合中的 arraylist 里的所有元素 |
remove() | 删除 arraylist 里的单个元素 |
size() | 返回 arraylist 里元素数量 |
isEmpty() | 判断 arraylist 是否为空 |
subList() | 截取部分 arraylist 的元素 |
set() | 替换 arraylist 中指定索引的元素 |
sort() | 对 arraylist 元素进行排序 |
toArray() | 将 arraylist 转换为数组 |
toString() | 将 arraylist 转换为字符串 |
ensureCapacity() | 设置指定容量大小的 arraylist |
lastIndexOf() | 返回指定元素在 arraylist 中最后一次出现的位置 |
retainAll() | 保留 arraylist 中在指定集合中也存在的那些元素 |
containsAll() | 查看 arraylist 是否包含指定集合中的所有元素 |
trimToSize() | 将 arraylist 中的容量调整为数组中的元素个数 |
removeRange() | 删除 arraylist 中指定索引之间存在的元素 |
replaceAll() | 将给定的操作内容替换掉数组中每一个元素 |
removeIf() | 删除所有满足特定条件的 arraylist 元素 |
forEach() | 遍历 arraylist 中每一个元素并执行特定操作 |
实例代码
java">
import java.util.ArrayList;
import java.util.Collections;public class Main {public static void main(String[] args) {/*数据结构——ArraryList*/ArrayList<String> strList = new ArrayList<>();//添加元素strList.add("Hello");strList.add("World");strList.add("Java");strList.add("Study");System.out.println(strList);//获取指定索引位置的元素System.out.println(strList.get(1));//修改指定索引位置的元素值strList.set(3,"My Study");System.out.println(strList);//获取元素数量System.out.println("当前ArraryList元素个数是"+strList.size());//循环遍历ArraryListfor(int i=0;i<strList.size();i++){System.out.println(strList.get(i));}for (String str : strList) {System.out.println(str);}//排序Collections.sort(strList);System.out.println(strList);//移除指定元素strList.remove("World");System.out.println(strList);//移除指定索引位置的元素strList.remove(2);System.out.println(strList);}
}
2.2 LinkedList
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的地址。
链表可分为单向链表和双向链表。
使用 LinkedList的情况 :
- 你需要通过循环迭代来访问列表中的某些元素。
- 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。
常用方法
方法 | 描述 |
public boolean add(E e) | 链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public void add(int index, E element) | 向指定位置插入元素。 |
public boolean addAll(Collection c) | 将一个集合的所有元素添加到链表后面,返回是否成功,成功为 true,失败为 false。 |
public boolean addAll(int index, Collection c) | 将一个集合的所有元素添加到链表的指定位置后面,返回是否成功,成功为 true,失败为 false。 |
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public boolean offer(E e) | 向链表末尾添加元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerFirst(E e) | 头部插入元素,返回是否成功,成功为 true,失败为 false。 |
public boolean offerLast(E e) | 尾部插入元素,返回是否成功,成功为 true,失败为 false。 |
public void clear() | 清空链表。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public boolean remove(Object o) | 删除某一元素,返回是否成功,成功为 true,失败为 false。 |
public E remove(int index) | 删除指定位置的元素。 |
public E poll() | 删除并返回第一个元素。 |
public E remove() | 删除并返回第一个元素。 |
public boolean contains(Object o) | 判断是否含有某一元素。 |
public E get(int index) | 返回指定位置的元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
public int indexOf(Object o) | 查找指定元素从前往后第一次出现的索引。 |
public int lastIndexOf(Object o) | 查找指定元素最后一次出现的索引。 |
public E peek() | 返回第一个元素。 |
public E element() | 返回第一个元素。 |
public E peekFirst() | 返回头部元素。 |
public E peekLast() | 返回尾部元素。 |
public E set(int index, E element) | 设置指定位置的元素。 |
public Object clone() | 克隆该列表。 |
public Iterator descendingIterator() | 返回倒序迭代器。 |
public int size() | 返回链表元素个数。 |
public ListIterator listIterator(int index) | 返回从指定位置开始到末尾的迭代器。 |
public Object[] toArray() | 返回一个由链表元素组成的数组。 |
public T[] toArray(T[] a) | 返回一个由链表元素转换类型而成的数组。 |
实例代码
java">import java.util.LinkedList;
import java.util.Collections;public class Main {public static void main(String[] args) {/*数据结构——LinkedList*/LinkedList<String> strList = new LinkedList<>();//添加元素strList.add("World");strList.add("Java");//在头部添加元素strList.addFirst("Hello");//在尾部添加元素strList.addLast("Study");System.out.println(strList);//获取指定索引位置的元素System.out.println(strList.get(1));//修改指定索引位置的元素值strList.set(3,"My Study");System.out.println(strList);//获取元素数量System.out.println("当前LinkedList元素个数是"+strList.size());//循环遍历ArraryListfor(int i=0;i<strList.size();i++){System.out.println(strList.get(i));}for (String str : strList) {System.out.println(str);}//排序Collections.sort(strList);System.out.println(strList);//移除指定元素strList.remove("World");System.out.println(strList);//移除指定索引位置的元素strList.remove(2);System.out.println(strList);}
}
2.3 HashMap
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 是无序的,即不会记录插入的顺序。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
HashMap 的 key 与 value 类型可以相同也可以不同,可以是字符串(String)类型的 key 和 value,也可以是整型(Integer)的 key 和字符串(String)类型的 value。
常用方法
方法 | 描述 |
clear() | 删除 hashMap 中的所有键/值对 |
clone() | 复制一份 hashMap |
isEmpty() | 判断 hashMap 是否为空 |
size() | 计算 hashMap 中键/值对的数量 |
put() | 将键/值对添加到 hashMap 中 |
putAll() | 将所有键/值对添加到 hashMap 中 |
putIfAbsent() | 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。 |
remove() | 删除 hashMap 中指定键 key 的映射关系 |
containsKey() | 检查 hashMap 中是否存在指定的 key 对应的映射关系。 |
containsValue() | 检查 hashMap 中是否存在指定的 value 对应的映射关系。 |
replace() | 替换 hashMap 中是指定的 key 对应的 value。 |
replaceAll() | 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。 |
get() | 获取指定 key 对应对 value |
getOrDefault() | 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值 |
forEach() | 对 hashMap 中的每个映射执行指定的操作。 |
entrySet() | 返回 hashMap 中所有映射项的集合集合视图。 |
keySet() | 返回 hashMap 中所有 key 组成的集合视图。 |
values() | 返回 hashMap 中存在的所有 value 值。 |
merge() | 添加键值对到 hashMap 中 |
compute() | 对 hashMap 中指定 key 的值进行重新计算 |
computeIfAbsent() | 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hasMap 中 |
computeIfPresent() | 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。 |
实例代码
java">
import java.util.HashMap;
import java.util.Collections;public class Main {public static void main(String[] args) {/*数据结构——HashMap*/HashMap<String,String> map = new HashMap<>();//添加元素map.put("101","Hello");map.put("102","World");map.put("103","Java");map.put("104","HashMap");System.out.println(map);//根据指定的key获取Value值System.out.println("Key值为101的元素Value值为:"+map.get("101"));//获取元素数量System.out.println("map的元素个数是:"+map.size());//修改Key 值为103的value值为 Java Studymap.replace("103","Java Study");System.out.println(map);//遍历HashMapmap.forEach((key,value)->{System.out.println("forEach Key:"+key+",forEach Value:"+value);});//遍历keyfor (String key : map.keySet()) {System.out.println("keySet() Key:"+key+",keySet() Value:"+map.get(key));}//遍历Valuefor(String value: map.values()) {// 输出每一个valueSystem.out.print(value + ", ");}//entrySet()遍历map.entrySet().forEach(entry->{System.out.println("entrySet().forEach Key:"+entry.getKey()+",entrySet().forEach Value:"+entry.getValue());});//移除指定keymap.remove("104");System.out.println(map);}
}
2.4 HashSet
HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。
HashSet 允许有 null 值。
HashSet 是无序的,即不会记录插入的顺序。
HashSet 不是线程安全的, 如果多个线程尝试同时修改 HashSet,则最终结果是不确定的。 您必须在多线程访问时显式同步对 HashSet 的并发访问。
HashSet 实现了 Set 接口。
常用方法
方法 | 描述 |
boolean add(E e) | 如果指定的元素尚不存在,则将其添加到此集合中 |
void clear() | 从该集中删除所有元素 |
Object clone() | 返回此 HashSet实例的浅表副本:未克隆元素本身 |
boolean contains(Object o) | 如果此set包含指定的元素,则返回 true |
boolean isEmpty() | 如果此集合不包含任何元素,则返回 true |
boolean remove(Object o) | 如果存在,则从该集合中移除指定的元素 |
int size() | 返回此集合中的元素数(基数) |
实例代码
java">
import java.util.HashSet;
import java.util.Collections;public class Main {public static void main(String[] args) {/*数据结构——HashSet*/HashSet<String> map = new HashSet<>();//添加元素map.add("Hello");map.add("World");map.add("Java");map.add("HashSet");map.add("HashSet");//重复的元素不会添加System.out.println(map);//获取元素数量System.out.println("map的元素个数是:"+map.size());//判断元素是否存在System.out.println("元素HashMap是否存在:"+map.contains("HashMap"));//遍历HashSetfor (String key : map) {System.out.println("元素值:"+key);}//移除指定元素map.remove("HashSet");System.out.println(map);}
}
3. 迭代器
迭代器(Iterator)是集合框架中的一种机制,是一种用于遍历集合(如列表、集合和映射等)的接口。
它提供了一种统一的方式来访问集合中的元素,而不需要了解底层集合的具体实现细节。
Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合。
Iterator 是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口。
常用方法
- next() - 返回迭代器的下一个元素,并将迭代器的指针移到下一个位置。
- hasNext() - 用于判断集合中是否还有下一个元素可以访问。
- remove() - 从集合中删除迭代器最后访问的元素(可选操作)
注意:Java 迭代器是一种单向遍历机制,即只能从前往后遍历集合中的元素,不能往回遍历。同时,在使用迭代器遍历集合时,不能直接修改集合中的元素,而是需要使用迭代器的 remove() 方法来删除当前元素。
如果迭代器一开始直接调用next()调用遍历过一次,第二次使用next()遍历时迭代器需要重新获取,否则会报错
实例代码
java">
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;public class Main {public static void main(String[] args) {/*数据结构——迭代器*/ArrayList<String> strList = new ArrayList<>();//添加元素strList.add("Hello");strList.add("World");strList.add("Java");strList.add("Study");// 获取迭代器Iterator<String> it = strList.iterator();// 输出集合中的第一个元素System.out.println(it.next());System.out.println(it.hasNext());// 输出集合中的所有元素do {System.out.println(it.next());} while (it.hasNext());//删除Study元素; 如果迭代器一开始直接调用next()调用遍历过一次,第二次使用next()遍历时迭代器需要重新获取,否则会报错it = strList.iterator();do {String itemValue=it.next();if(itemValue.equals("Study")){it.remove();}} while (it.hasNext());System.out.println(strList);}
}