一.集合框架(单列集合)
1.概述
集合:长度可变;只能存储引用数据类型,即使存储了基本类型,到了集合中也会自动装箱成包装类;集合有很多方法,直接操作元素
2.分类
- 单列集合:元素只由一部分构成
- list.add(“abc”)
- 双列集合:一个元素由两部分构成
- (key,value) ->(键,值) ->键值对
- map.put(1,“zsy”);
3.与数组区别
数组定长,集合不定长,都是一次存储多个数据,在数组中添加数据,如果数组长度不够,需要创建新数组,将老数组复制过来,最后添加新元素,很麻烦,而集合直接添加就行
4.集合框架
二.Collection接口
单列集合顶级接口
创建:
Collection<E> 集合名 = new 实现类对象<E>() <E>:泛型
泛型:规定集合中元素的数据类型,统一类型的;泛型类型只能写引用类型,不能写基本类型,如果不写泛型,默认为Object类型
<String> 元素为字符串
<Integer> 元素为整数
<Person> 元素为Person对象
<Double> 元素为double型小数
常用方法:
1.boolean add(E e) : 将给定的元素添加到当前集合中(一般调add时,不用boolean接收,因为add一定会成功)
2.boolean addAll(Collection<? extends E> c) :将另一个集合元素添加到当前集合中 (集合合并)
3.void clear():清除集合中所有的元素
4.boolean contains(Object o) :判断当前集合中是否包含指定的元素
5.boolean isEmpty() : 判断当前集合中是否有元素->判断集合是否为空
6.boolean remove(Object o):将指定的元素从集合中删除
7.int size() :返回集合中的元素个数。
8.Object[] toArray(): 把集合中的元素,存储到数组中
public class Demo01 {
public static void main(String[] args) {
Collection<String> collection1 = new ArrayList<>();
//add(E e)将给定的元素添加到当前集合中
collection1.add("张三");
collection1.add("李四");
collection1.add("王五");
collection1.add("赵六");
collection1.add("刘七");
collection1.add("陈八");
System.out.println(collection1);
//addAll(Collection<? extends E> c)将另一个集合元素添加到当前集合中 (集合合并)
ArrayList<String> collection2 = new ArrayList<>();
collection2.addAll(collection1);
System.out.println(collection2);
//void clear():清除集合中所有的元素
collection2.clear();
System.out.println(collection2);
//boolean contains(Object o) :判断当前集合中是否包含指定的元素
boolean s = collection1.contains("赵六");
System.out.println(s);
//boolean isEmpty() : 判断当前集合中是否有元素->判断集合是否为空
boolean empty = collection1.isEmpty();
System.out.println(empty);
//boolean remove(Object o):将指定的元素从集合中删除
collection1.remove("陈八");
System.out.println(collection1);
//int size() :返回集合中的元素个数。
int size = collection1.size();
System.out.println(size);
//Object[] toArray(): 把集合中的元素,存储到数组中
Object[] arr = collection1.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
三.迭代器Iterator
1.概述
Iterator接口
获取:
Collection中的方法: -> 只要是Collection的实现类都可以用iterator获取迭代器对象,遍历
Iterator iterator()
方法:
boolean hasNext() -> 判断集合中有没有下一个元素
E next() -> 获取下一个元素
public class Demo02 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
//获取Iterator
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){//判断有没有下一个元素;boolean hasNext()
String element = iterator.next();//如果有获取下一个元素给element; E next()
System.out.println(element);
}
}
}
注意:在迭代的过程中,不要连续调用多次next方法
如下例子:
public class Demo03 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("田七");
list.add("王五");
list.add("李四");
list.add("赵六");
//获取iterator
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
System.out.println(iterator.next());
}
}
}
会出现没有可操作的元素异常NoSuchElementException
2.迭代器迭代过程
3.迭代器底层原理
ArrayList<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
list.iterator方法调用之后被Iterator接口类型接受了,那么Iterator接受的肯定是实现类对象
例如:使用ArrayList集合做迭代时,Iterator接口接收的是ArrayList的内部类Itr
Iterator指向Itr这个实现类,只有在遍历ArrayList时才是,其他的集合在迭代的时候Iterator接收的是其他的实现类对象,比如HashSet
4.并发修改异常
在使用迭代器的过程中随意修改集合长度,就会报"并发修改异常ConcurrentModificationException
例如:定义一个集合,存储"张三",“李四”,“王五”,“田七”,迭代元素,如果迭代到王五,就添加"赵六"
public class Demo04 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("田七");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
if ("王五".equals(element)) {
list.add("赵六");
}
}
System.out.println(list);
}
}
底层报错原理:实际操作次数和预期操作次数不相等时,抛异常,刚开始,实际操作次数和预期操作次数是相等的,但是我们调用了add方法,add方法底层只给实际操作次数加1了,并没有重新给预期操作次数加1,此时再调用next方法,底层实际操作次数和预期操作次数不相等了,所以抛出了"并发修改异常"
Iterator<String> iterator = list.iterator();
String element = iterator.next();
=================================================
private class Itr implements Iterator<E> {
/*
expectedModCount:预期操作次数
modCount:实际操作次数
*/
int expectedModCount = modCount;
public E next() {
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)//如果实际操作次数和预期操作次数不相等,抛异常
throw new ConcurrentModificationException();
}
list.add("赵六");
======================================
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
}
解决:ListIterator listIterator()
public class Demo05 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("田七");
ListIterator<String> stringListIterator = list.listIterator();
while (stringListIterator.hasNext()) {
String element = stringListIterator.next();
if ("王五".equals(element)) {
stringListIterator.add("赵六");
}
}
System.out.println(list);
}
}