Collection,List,Set之间的关系及使用方法
1.Collection集合概述及使用
概述:
- 是单列集合的顶层接口,它表示一组对象,这些对象也称为Collection集合的元素
- JDK不支持此接口的任何直接实现,它提供更具体的子接口(List和Set)实现
创建Collection集合的对象:
-
多态的方式
-
具体的实现类ArrayList,LinkedList
2. Java集合体系结构
3. Collection
- Collection集合常用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HcyUTCQx-1631862667820)(C:\Users\ZZ09J1672\AppData\Roaming\Typora\typora-user-images\image-20210914143603502.png)]
- 存储并遍历Mentor对象
public static void CollectionMentor(){
Collection<Mentor> c = new ArrayList<>();
Mentor m1 = new Mentor("井川里予" , 18);
Mentor m2 = new Mentor("M哥" , 22);
Mentor m3 = new Mentor("紫菜蛋花兔" , 20);
c.add(m1);
c.add(m2);
c.add(m3);
Iterator<Mentor> it = c.iterator();
while (it.hasNext()){
Mentor m = it.next();
System.out.println(m);
System.out.println(m.getName()+","+m.getAge());
}
}
3.1 List集合
List集合概述及特点
概述:
- 有序集合(也称为序列),使用者可以精确控制列表中每个元素的插入顺序,可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表允许重复的元素
特点:
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
List集合特有方法
注:E代表元素
List除了迭代器遍历,也可以用for循环+get(int index)遍历
//遍历List集合
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
并发修改异常
CocurrentModificationException:当不允许这样的修改时,可以通过检测到对象的并发修改的方法来抛出此异常。
public static void ListMentor(){
List<Mentor> c = new ArrayList<>();
Mentor m1 = new Mentor("井川里予" , 18);
Mentor m2 = new Mentor("M哥" , 22);
Mentor m3 = new Mentor("紫菜蛋花兔" , 20);
c.add(m1);
c.add(m2);
c.add(m3);
Iterator<Mentor> it = c.iterator();
while (it.hasNext()){
Mentor m = it.next();
if(m.getName().equals("井川里予")){
c.add(new Mentor("Marry me",21));
}
System.out.println(m);
System.out.println(m.getName()+","+m.getAge());
}
}
运行结果
产生原因
- 迭代器遍历过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致(详细原理可以查看ArrayList源码)
源码分析(只摘出来相关的部分代码)
List-> AbstractList-> ArrayList-> iterator()-> new Iter()-> next()-> checkForComodification()
public interface List<E> extends Collection<E> {
void add(int index, E element);
Iterator<E> iterator();
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
protected transient int modCount = 0;
}
//modCount:实际修改集合的次数
//expectedModCount:预期修改集合的次数
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
public Iterator<E> iterator() {
return new Itr();
}
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;//modCount在此+1
}
private class Itr implements Iterator<E> {
int cursor;
int lastRet = -1;
int expectedModCount = modCount;//因为继承了AbstractList类,所以能访问到modCount
Itr() {}
public boolean hasNext() {
return cursor != size;
}
public E next() {
checkForComodification();
}
//例子中调用next方法之后,又调用了add()方法,add()方法中modCount+1,所以在下一次调用next()方法中的checkForComodification()方法后,因为modCount != expectedModCount,所以报并发修改异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
}
解决方案一
- 用for循环遍历,然后用集合对象做对应的操作即可
for(int i = 0;i<c.size();i++){
Mentor m = c.get(i);
if(m.getName().equals("井川里予")){
c.add(new Mentor("Marry me",21));
}
System.out.println(m.getName()+","+m.getAge());
}
解决方案二
- 用ListIterator : 列表迭代器
- 通过List的集合的listIterator()方法得到,所以说它是List集合特有的迭代器
ListIterator<Mentor> lit = c.listIterator();
while (lit.hasNext()){
Mentor m = lit.next();
if(m.getName().equals("井川里予")){
lit.add(new Mentor("Marry me",21));
}
System.out.println(m.getName()+","+m.getAge());
}
LinkedList特有方法
3.2 Set集合
Set集合概述及特点
概述:
- 不包含重复元素的集合,并且最多只有一个空元素
特点:
- 不包含重复元素
- 没有带索引的方法,所以不能使用普通for循环遍历
public static void setMethod(){
Set<String> set = new HashSet<>();
//HashSet:底层数据结构是哈希表,对集合的迭代顺序不做任何保证
set.add("hello");
set.add("world");
set.add("java");
set.add("world");
for(String s : set){
System.out.println(s);
}
}
运行结果