List接口下的集合

前言:

集合简介
  1. 集合定义:
    存储数据的容器,是对普通数据结构的封装。
  2. 集合和其他容器的比较:
    数据库:数据可以长时间存储,从而可以使数据反复使用。
    数组/集合:项目运行起来使存入数据,一旦项目结束数据就不存在了,起到暂存作用。
  3. 数组和集合的比较:
    1. 数组是静态的,集合是动态的。
    2. 数组是Java内置类型,效率更高,但集合功能更加全面。
    3. 数组需要指定类型,集合则可有可无。
    4. 数组既可以使用普通类型,也可以使用引用类型,而集合只能使用引用类型。
  4. 集合和数组的选择:
      对元素的数量有明确判断后续不会有太多复杂操作的时候,选择数组。集合反之。
集合框架库概述(部分)

在这里插入图片描述

  1. Iterator:迭代器遍历集合,可以从前向后遍历。
  2. ListIterator:是Iterator的子接口,可以进行双向遍历。
  3. Collection:是存放一组单值的最顶层的接口。
  4. List:是Collection的子接口,对Collection进行了大量扩充,允许重复和空值,并且是有序的。
  5. Set:是Collection的子接口,没有对Collection进行扩充,不允许重复。SortedSet:单值的排序接口。
  6. Queue:是Collection的子接口,具有先入先出的特点。
  7. Map:是存放一对值得最顶层的接口,即接口中的每个元素都是以key—value的键值对形式保存到的。
  8. SortedMap:Map的子接口,存放键值对的排序接口。

  所有的接口要么是Map接口下的,要么是Collection接口下的。因此要么存放单值,要么存放双值。

一、ArrayList

底层

采用数组结构

继承的接口

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  1. List:存放单值。允许重复和空值并且有序。
  2. RandomAccess:表示ArrayList可以被随机访问。
  3. Cloneable:集合可以使用clone方法。
  4. Serializable:可序列化,表示ArrayList可以进行序列化操作。

方法

public static void main(String[] args) {
    ArrayList<Integer> arr1 = new ArrayList<>();
    //增
    arr1.add(1);
    arr1.add(1,8);//下标,插入的值
    
    //遍历
    Iterator<Integer> iterator = arr1.iterator();
    while(iterator.hasNext()){
        System.out.print(iterator.next()+"  ");
    }
  
    //遍历
    ListIterator<Integer> listIterator = arr1.listIterator();
    while(listIterator.hasNext()){
        System.out.print(listIterator.next()+"  ");
    }
    
    //删
	arr1.remove(1);//按下标
	Integer inc = 3;
    arr2.remove(inc);//按元素
    
    //改
	arr1.set(1,10);

	//子集
	List<Integer> arr1 = arr.subList(1,3);//[1,3)

	//并集
	arr4.addAll(arr3);//将arr3中的全部元素插入到arr4最后
	arr4.addAll(1,arr3);//将arr3的所有元素插入到arr4的该下标后

	//差集
	arr4.removeAll(arr3);//将arr4中所有arr3中的元素删除

	//求不重复并集
    ArrayList<Integer> arr5 = new ArrayList<>();
    arr5.add(1);arr5.add(2);arr5.add(3);
    ArrayList<Integer> arr6 = new ArrayList<>();
    arr6.add(3);arr6.add(4);arr6.add(5);
    
    ArrayList<Integer> arr7 = new ArrayList<>();
    arr7.addAll(arr5);arr7.addAll(arr6);//1 2 3 3 4 5
    arr6.retainAll(arr5);//3     //交集
    arr7.removeAll(arr6);//1 2 4 5    //差集
    arr7.addAll(arr6);//1 2 4 5 3
    for (Object a:arr7) {
        System.out.print(a+"  ");
    }
}

源码分析

构造器
public ArrayList(int initialCapacity) {//有参构造
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
}

public ArrayList() {//无参构造,默认为空数组
    super();
    this.elementData = EMPTY_ELEMENTDATA;
}
grow方法
private void grow(int minCapacity) {
    int oldCapacity = elementData.length; //原数组大小
    int newCapacity = oldCapacity + (oldCapacity >> 1);//新数组大小
    if (newCapacity - minCapacity < 0) //第一次扩容时将数组大小定为10
        newCapacity = minCapacity;  //10
    if (newCapacity - MAX_ARRAY_SIZE > 0)//数组容量非常庞大的时候判断新数组大小是否超过默认容量上限
        newCapacity = hugeCapacity(minCapacity);//如果超过将最大容量返回回来
    elementData = Arrays.copyOf(elementData, newCapacity);//扩容
}

总结

ArrayList在创建对象时默认为空数组,添加数据时才开始扩容。第一次扩容为10,其后1.5倍扩容。
优点:适合做随机访问。
缺点:不适合做随机的插入删除,会有大量的数据移动。

二、LinkedList

底层

采用双向链表结构

继承的接口

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
  1. List:存放单值。允许重复和空值并且有序。
  2. Deque:queue的子接口,双端队列接口。
  3. Cloneable:集合可以使用clone方法。
  4. Serializable:可序列化,表示ArrayList可以进行序列化操作。

方法

public static void main(String[] args){
	LinkedList<Integer> linkedList = new LinkedList();
	//增
    linkedList.add(1);//尾插
	linkedList.add(1, 2)//下标,元素
	linkedList.addFirst(3)//头插
	linkedList.push(4)//当用链式结构实现栈时,进栈
	
	//删
	linkedList.removeFirst()//头删
	linkedList.remove(1)//删除1元素
	linkedList.remove(1)//下标
	linkedList.pop()//当用链式结构实现栈时,出栈操作
	
	//改
	linkedList.set(110)//下标,元素
	
	//查
	linkedList.peekFirst()//查询第一个
	linkedList.peekLast()//查询最后一个
	linkedList.get(1)//查询1号位置的元素
}

源码分析

构造器
//无参构造:链表的添加不需要开辟空间
public LinkedList() {
}
//有参构造:将集合传入
public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}
删除操作
 E unlink(Node<E> x) {
        // assert x != null;
        final E element = x.item;
        final Node<E> next = x.next;
        final Node<E> prev = x.prev;
        if (prev == null) { //前驱为空
            first = next;
        } else {
            prev.next = next;
            x.prev = null;//gc
        }
        if (next == null) {//后继为空
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;//gc
        }
        x.item = null;//gc
        size--;
        modCount++;//快速失败机制
        return element;
    }

总结

LinkedList没有容量这一说,更不需要扩容。
LinkedList的优点:插入删除操作不需要数据移动,适合时常需要数据更新的情况。
缺点:不适合做随机访问,需要遍历链表。

三、Vector

继承的接口

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable

与ArrayList一致。

方法

Vector集合中增删改查,遍历方法,迭代器与ArrayList相同。

源码分析

构造器
//双惨构造函数                         (增长因子)
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}

//调用双参构造器,增长因子默认为0
public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}
//无参构造,默认初始容量为10
public Vector() {
    this(10);
}
grow方法
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //增长因子大于0时,按照增长因子扩容,否则按照两倍扩容
    int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                     capacityIncrement : oldCapacity);
//当初始容量为0,增长因子为-1时,为了防止扩容后容量还是0,所以添加的条件,新容量不能小于最小应该扩的容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);//如果超过将最大容量返回回来
    elementData = Arrays.copyOf(elementData, newCapacity);//扩容
}

总结

ArrayList 和LinkedList 的异同

  1. 从继承的接口来看:
    ArrayList比 LinkedList多实现一个RandomAccess,用来表明其支持随机访问。LinkedList比ArrayList多实现一个Deque,具有队列先入先出的特点。此接口的子类可以实现队列操作。
  2. 底层实现上来看
  • ArrayList底层用数组实现,LinkedList底层用双链表来实现。
    因为数组的访问只需要给定下标,就可以立即访问,而链表需要遍历,遍历的次数即为下标值。
  • ArrayList 的 get() ,set()方法相对于LinkedList效率要高,ArrayList的查询以及获取元素,效率更高。
  • 数组随机添加一个元素,指定下标的元素以及后面的所有元素,都需要向后移动,开销很大,而链表只需要将指定位置下标的上一个的节点确定,改变引用即可,开销很小。linkedList的增删效率更高。
  1. 使用场景
    如果需要增删频繁,则使用LinkedList;
    如果需要查询操作频繁,则使用ArrayList;

ArrayList 和Vector的异同

  1. 从继承的接口来看:
    实现的接口相同,特点相同
  2. 底层实现上来看
    都是数组实现,调用方法没有区别
  3. 从源码上来看
  • 构造方法
    ArrayList的初始数组大小为
    Vector的初始数组大小为10
  • 扩容方法:
    ArrayList 以1.5倍扩容,如果目前元素时1000,再增加1个,则要1.5倍扩容,会造成499个空间浪费
    Vector默认2倍扩容,如果增长因子大于零,则扩容增长因子个大小。
  • 线程安全问题:
    Vector:方法都用了Synchronized 来修饰,是线程安全的。
    ArrayList :没有加锁是线程不安全的。
  1. 使用场景
    如果需要考虑线程安全问题,则选择Vector
    如果不考虑线程安全问题,则选择ArrayList
    因为加锁操作非常耗时,所以不考虑线程安全问题时不使用Vector
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值