Java集合-----List接口及其实现类:ArrayList、LinkedList、Vector

文章目录

  • List接口概述
  • List接口的常用方法
  • List接口的实现类
    • ArrayList源码分析
      • 类继承关系
      • ArrayList中的属性:
      • ArrayList构造函数:
      • ArrayList中常用方法
        • 添加操作:add()
        • 删除操作:remove()
        • 获取元素:get()
        • ArrayList是如何实现序列化的?
      • ArrayList的总结
    • LinkedList源码分析
      • 类继承关系
      • 类成员属性
      • 类构造器
      • LinkedList的List特性:
      • LinkedList的Queue特性
      • 总结
    • Vector
      • 类继承关系
      • 类成员属性
      • 类构造器
      • Vector的扩容机制
      • 增删改查
      • 为什么现在不提倡使用Vector?
      • 总结

List接口概述

List接口是Collection接口的一个子接口。

List接口的特点:

        1.有序[存储有序]

        2.数据可重复

        3.可以存储null值

        4.可以根据index查找相应的元素。

List接口的常用方法

void add(int index,E element):在指定index位置处添加元素element.

boolean addAll(int index,Collection<? extends E>c):在指定index位置处插入指定集合的所有元素

E remove(int index):删除index位置上的元素

E set(int index,E element):修改index位置上的元素为element。

E get(int index):获取指定位置上的元素

int indexOf(Object o):从左往右查找,获取o的位置,若o不存在,返回-1int lastIndexOf(Object o):从右往左找,获取o的位置,若不存在,返回-1.

List<E> subList(int fromIndex,int toIndex):截取从fromIndex开始到toIndex-1处的元素,并返回一个新的List

List接口的实现类

ArrayList源码分析

ArrayList是List接口的实现类之一,ArrayList底层存储数据以数组存储的。

类继承关系

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

ArrayList继承AbstractList类,实现了List接口,可以被序列化,也可以被克隆,支持快速随机访问。

ArrayList中的属性:

    private static final long serialVersionUID = 8683452581122892189L; //版本号
    private static final int DEFAULT_CAPACITY = 10;// 底层数组的默认容量
    private static final Object[] EMPTY_ELEMENTDATA = {
   }; //存储数据的数组
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {
   }; // 存储数据的数组
    transient Object[] elementData; //存储数据的数组
    private int size; //元素个数
    // 数组的最大容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

我们可以看到,ArrayList的底层数组默认容量时10,但是我们看到了三个用于存储数据的的数组,其中两个被声明为空数组,一个还没有被初始化。这是什么原因呢?别着急,我们先来看一看ArrayList的构造函数:

ArrayList构造函数:

 public ArrayList() {
   
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
 public ArrayList(int initialCapacity) {
   
        if (initialCapacity > 0) {
   
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
   
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
   
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
   
  public ArrayList(Collection<? extends E> c) {
   
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
   
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
   
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

我们可以看到,ArrayList为我们提供了三种构造函数,分别是:无参构造函数、带一个int类型参数的构造函数,以及一个Collection类型参数的构造函数

当我们调用无参构造函数时,就会将我们的DEFACULT_EMPTY_ELEMENTDATA赋值给element,即当我们调用了空参构造器时,会将element初始化成一个空数组

当我们调用带一个int类型参数的有参构造时,如果 initialCapacity>0,则会按照我们给定的容量去初始化底层存储数据的数组。如果initialCapacity==0,则会将EMPTY_ELEMENTDATA赋给elementData。

当我们调用Collection参数类型的构造器时,会将指定的Collection集合中的元素拷贝到该ArrayList中,如果失败,则用EMTY_ELEMENTDATA赋值。

所以,通过构造函数我们就可以知道,DEFALUT_EMPTY_ELEMENTDATA和EMPTY_ELEMENTDATA这两个数组就是为了区分调用的是哪一个构造器而设定的。

ArrayList中常用方法

添加操作:add()
    public boolean add(E e) {
   
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

add()方法中调用了ensureCapacityInternal()方法,然后再向elementData中添加元素。
我们来看一看ensureCapacityInternal():

	 private void ensureCapacityInternal(int minCapacity) {
   
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

	private static 

你可能感兴趣的:(Java集合,java,集合)