Collection,List,Set之间的关系及使用方法

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());
    }
}

运行结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EdspzoXd-1631862667826)(C:\Users\ZZ09J1672\AppData\Roaming\Typora\typora-user-images\image-20210914175849315.png)]

产生原因

  • 迭代器遍历过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致(详细原理可以查看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());
}

运行结果[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OKgvIvoC-1631862667828)(C:\Users\ZZ09J1672\AppData\Roaming\Typora\typora-user-images\image-20210916141204717.png)]

解决方案二

  • 用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);
    }
}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex Sunspot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值