容器之List

文章详细介绍了Java中的容器概念,特别是List接口及其常用的实现类ArrayList和LinkedList。重点讲解了ArrayList的动态扩容机制,从无参构造器的初始化到add方法的执行,再到grow()方法的调用,展示了ArrayList如何在需要时增加容量以适应元素的增长。LinkedList作为双向列表的特点也被提及。
摘要由CSDN通过智能技术生成

前言:

什么是容器:容器就好像一个存放对象的仓库,可以将你的东西存放在一个无限制的仓库中,然后要用的时候可以取出来

接口List

List接口是继承Collection接口

他常用的实现类:ArrayList、linkedList、Vector

List接口方法

void add(E element)
在末尾添加元素。
    
void add(int index, E element)
在指定位置插入元素,后面的元素都往后移一个元素。
    
boolean addAll(int index, Collection<? extends E> c)
在指定的位置中插入c集合全部的元素,如果集合发生改变,则返回true,否则返回falseE get(int index)
返回list集合中指定索引位置的元素
    
int indexOf(Object o)
返回list集合中第一次出现o对象的索引位置,如果list集合中没有o对象,那么就返回-1
    
ListIterator<E> listIterator()
返回此列表元素的列表迭代器
    
ListIterator<E> listIterator(int index)
从指定位置开始,返回此列表元素的列表迭代器。
    
E remove(int index)
删除指定索引的对象
    
E set(int index, E element)
在索引为index位置的元素更改为element元素
    
List<E> subList(int fromIndex, int toIndex)
返回从索引[fromIndex,toIndex)的元素集合,包左不包右
      

ArrayList

ArrayList特点:本质是数组,他是基于数组封装的一个容器 ,所以他是查询快、有序列的、增删慢。

//遍历ArrayList方法
public class arrayList01{
    public static void main(String []args){
        List<Integer> list=new ArrayList<Integer>();
        //使用List接口的方法添加元素
        list.add(1);
       	 ……
       	 ……
        for(int every:list){
            System.out.print(every+"\t")
        }	
    }
}

ArrayList的动态扩容

​ 上面我们说了ArrayList本质是数组,那么它是如何实现数组的动态扩容的让我们一起来分析源码,首先我们先看ArrayList无参构造器都干了什么。以下是ArrayList无参构造器的源码:

/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

​ 此时我们可以看到elementData变量以及DEFAULTCAPACITY_EMPTY_ELEMENTDATA常量,我们看看这两个是什么

elementData

大概意思就是这是一个数组缓冲区,集合实际长度就等于这个数组的长度

	/**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

DEFAULTCAPACITY_EMPTY_ELEMENTDATA

大概意思是 一个空数组实例用于默认大小

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

那么就可以说使用无参构造器创建的ArrayList集合就是一个空的长度为0的集合

this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

那么它又是怎么进行动态扩容的?我们来看它add(E e)方法

  • size : ArrayList 大小(包含元素个数)

  • elementData 上面介绍过的数组缓冲区

  • modCount++;记录集合的操作次数,继承自abstractList.

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

​ 有上面代码可见add(E e)方法又调用了它的重载函数add(e, elementData, size); 我们继续深入查看

  1. if (s == elementData.length)它先是做了一个判断,查看当前集合元素个数是否和数组缓冲区大小相等,如果相等调用grow()方法否则添加这个元素
/**
     * This helper method split out from add(E) to keep method
     * bytecode size under 35 (the -XX:MaxInlineSize default value),
     * which helps when add(E) is called in a C1-compiled loop.
     */
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

grow()调用了它的重载方法

private Object[] grow() {
    return grow(size + 1);
}
动态扩容的本质
  1. DEFAULT_CAPACITY=10:默认容量为10
  2. minCapacity:size+1
  • oldCapacity:数组缓冲区的长度

  • if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) 判断数组缓冲区的长度是否大于0; 数组缓冲区是否不等于使用无参构造器创建ArrayList时赋值的默认空数组。

    简单理解这个就是判断这个集合是否是第一次使用的

 /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero
     */
    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
 	//如果不是第一次使用则判断使用ArraysSupport.newLength(int oldLength, int minGrowth, int prefGrowth)判断容量增长的长度,然后返回的复制数组
        if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            int newCapacity = ArraysSupport.newLength(oldCapacity,
                    minCapacity - oldCapacity, /* minimum growth */
                    oldCapacity >> 1           /* preferred growth */);
            return elementData = Arrays.copyOf(elementData, newCapacity);
            
        } 
        //如果是第一次使用数组让elementData数组缓冲区等于一个新的数组并返回,其数组长度等于size+1>10 ?  size+1:10;
        else {
            return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
        }
    }

LinkedList

LinkedList类是双向列表,列表中的每个节点都包含了对前一个和后一个元素的引用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值