Java集合框架图:
由上图可知容器主要分为List、Set和Map三种,其中List和Set拥有共同的父接口Collection。List、Set和Map我会在后面的文章中分别详细介绍。
Collection接口继承了Iterable接口,意味着Collection及其实现类都是可迭代的,Iterable的迭代则依赖于迭代器Iterator。
Iterator迭代器
//是否还有下一个元素
boolean hasNext();
//返回下一个元素的引用并将指针指向下一个元素
E next();
//删除集合中的元素
void remove()
用ArrayList举例如:
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(4);
intList.add(11);
intList.add(7);
Iterator<Integer> iterator = intList.iterator();
while (iterator.hasNext()) {
Integer num = iterator.next();
System.out.print(num + " ");
if (num == 11) {
iterator.remove();
}
}
System.out.println("删除后的list长度为:" + intList.size());
执行结果:
1 4 11 7 删除后的list长度为:3
需要注意的是next()方法只可以调用一次,调用超过一次就会导致有元素没有被遍历到,例如:
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(4);
intList.add(11);
intList.add(7);
Iterator<Integer> iterator = intList.iterator();
while (iterator.hasNext()) {
Integer num = iterator.next();
iterator.next();
System.out.print(num + " ");
if (num == 4) {
iterator.remove();
}
}
System.out.println("删除后的list长度为:" + intList.size());
执行结果:
1 11 删除后的list长度为:4
ListIterator
ListIterator接口继承了Iterator接口,相比Iterator,listIterator拥有更强大的功能,ListIterator可以逆向遍历且可以向集合的指定位置添加元素,但仅限于List的实现类使用。
//是否还有下一个元素
boolean hasNext();
//返回下一个元素的引用并将指针指向下一个元素
E next();
//删除集合中的元素
void remove()
//如果迭代器以逆向遍历,迭代器指向的元素前还有元素返回true,否则返回false
boolean hasPrevious();
//返回迭代器指向位置的前面的一个元素并将指针指向前一个元素
E previous();
//返回迭代器指向元素的后面一个元素的索引
int nextIndex();
//返回迭代器指向元素的前面一个元素的索引
int previousIndex();
//将迭代器指向的前面的元素替换为e
void set(E e);
//将元素e插入到迭代器指向位置的前面
void add(E e);
还是用ArrayList举例:
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(4);
intList.add(11);
intList.add(7);
ListIterator<Integer> listIterator = intList.listIterator();
while (listIterator.hasNext()) {
Integer num = listIterator.next();
System.out.print("当前元素:" + num);
if (num == 4){
System.out.print(" 元素4的后一个元素的索引为:" + listIterator.nextIndex());
listIterator.set(6);
listIterator.add(5);
}
System.out.println();
}
System.out.println("逆序遍历-------------");
while (listIterator.hasPrevious()) {
Integer num = listIterator.previous();
System.out.println("当前元素:" + num);
if (num == 11) {
System.out.println("元素11的前一个元素的索引为:" +
listIterator.previousIndex());
}
}
执行结果:
当前元素:1
当前元素:4 元素4的后一个元素的索引为:2
当前元素:11
当前元素:7
逆序遍历-------------
当前元素:7
当前元素:11
元素11的前一个元素的索引为:2
当前元素:5
当前元素:6
当前元素:1
Collection接口
//向集合中添加元素,添加成功返回true,失败返回false
boolean add(Object e);
//将指定集合的全部元素添加到此集合中
boolean addAll(Collection<? extends E> c);
//清空集合的元素
void clear();
//判断集合中是否包含指定元素,如果集合允许有null,也可以对null判断
boolean contains(Object o);
//此集合中是否包含指定集合中的全部元素
boolean containsAll(Collection<?> c);
//判断集合是否为空集合
boolean isEmpty();
//删除集合中的指定元素
boolean remove(Object o);
//删除此集合中所有等于指定集合中的元素
boolean removeAll(Collection<?> c);
//取得两个集合的交集
boolean retainAll(Collection<?> c);
//获取集合的元素个数
int size();
//返回包含此集合中所有元素的数组,但类型为Object[]
Object[] toArray();
//返回包含此容器中所有元素的数组,且指定该数组的运行时类型
<T> T[] toArray(T[] a)
快速失败机制
是集合的一种错误检测机制,当多个线程对集合进行结构上的改变或单个线程违反规则(例如迭代时调用集合的remove()方法)时,可能会抛出ConcurrentModificationException异常。
多线程环境下:a线程在遍历集合时,b线程修改了集合的结构;
单线程环境下:使用增加for循环遍历集合或使用迭代器遍历集合时,使用集合自身的方法修改了集合结构。
数组与集合的转换
数组转集合
String[] ary = {"1","2"};
List<String> list = Arrays.asList(ary);
集合转数组
1.得到的是Object[]类型的数组
List<String> list = new ArrayList();
Object[] ary = list.toArray();
2.得到的是指定类型的数组
List<String> list = new ArrayList();
String[] arr = new String[list.size()];
String[] strArr = list.toArray(arr);
遍历的几种方法
- for循环遍历
- 增强for循环遍历
- 迭代器遍历
例子就不举了,需要注意的是使用增强for循环遍历时,不能修改集合的结构(包括增加和删除元素);使用迭代器遍历时,不能使用除迭代器外的方法修改集合结构。其主要原因是List和Map在实现时定义了一个继承Iterator的内部类,内部类中有一个叫expectedModCount的属性,初始值为集合大小,使用迭代器遍历时的各个方法都会首先判断该属性与集合大小是否相同,只有使用迭代器修改集合结构才会维护该值。增强for循环实际上也是调用的迭代器进行遍历。