ArrayList源码分析

ArrayList源码分析

一、基本类图

在这里插入图片描述

二、List中的方法

1、遍历ArrayList的几种方法

 List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        //遍历list
        //1.迭代器
        Object next = null;
//        Iterator iterator = list.iterator();
//        while (iterator.hasNext()) {
//            //next每次会被赋予不同的值
//            next = iterator.next();
//            //所以要每次输出
//            System.out.println(next);
//        }
//        while(iterator.hasNext()){
//            next = iterator.next();
//            System.out.println(next);
//        }
        //2.增强器(底层也是使用迭代器实现)
        for(int i : list){
            System.out.println(i);
        }
迭代器遍历
Iterator iterator = list.iterator();//调用iterator方法(迭代器),返回一个迭代器
while(iterator.hasNext){//迭代器有下一个就进入
    //迭代器最开始指向空(数组第一个元素的上一个位置)
    //所以指针下移一位后得到数组第的一个元素
    Object o = iterator.next();//将遍历到的值赋值给o
    System.out.println("o=>"+o);
}
增强for循环
for(Object o : list){//底层同样是迭代器
    System.out.println("o=>"+o);
}
普通for循环
for(int i=0; i<list.size(); i++){
   System.out.println("o=>"+list.get(i));
}

2、ArrayList中的方法

package com.liu.List;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.util.function.UnaryOperator;

/**
 * list方法练习
 */
public class List_ {
    public static void main(String[] args) {
        List<Object> list = new ArrayList<>();
        //size()  数组的大小
        System.out.println("size()=>"+list.size());
        //add(index)添加   向list的结尾填加元素
        list.add("liuzhiyuan");
        list.add("hongrundong");
        list.add("sujiantao");
        list.add("kkk");
        System.out.println("list=>"+list);
        //add(index,element)  在指定位置添加元素
        list.add(1,"kkk");
        System.out.println("list=>"+list);
        //isEmpty()  判断集合是否为空
        System.out.println("isEmpty()=>"+list.isEmpty());
        //get(index)获取指定下标的元素
        System.out.println("get()=>"+list.get(1));
        //listIterator(index)从指定位置开始一直到末尾
        ListIterator<Object> lsitIterator = list.listIterator(1);
        while (lsitIterator.hasNext()) {
            Object next =  lsitIterator.next();
            System.out.println("listIterator=>"+next);
        }
        //addAll(Collection) 将一个新的集合添加到原集合后
        List list1 = new ArrayList<>();
        list1.add("new List");
        list.addAll(list1);
        System.out.println("addAll()=>"+list);
        //clear()  清空所有list中的元素
        //list.clear();
        //System.out.println("list=>"+list);

        System.out.println("equals=>"+list.equals(list1));
        //contains(Object)  判断list中是否存在object这个元素
        //containsAll(Collection) 判断list是否包含list1中所有元素
        System.out.println("contains()=>"+list.contains("kkk"));
        System.out.println("containsAll()=>"+list.containsAll(list1));

        System.out.println("hashCode()+>"+list.hashCode());

        System.out.println("list=>"+list);
        //indexOf(Object o)  返回list中object元素所在的第一个位置
        System.out.println("indexOf()=>"+list.indexOf("kkk"));
        //lastIndexOf(Object o) 返回list中 o所在的最后一个位置
        System.out.println("lastIndexOf()=>"+list.lastIndexOf("kkk"));

        //remove(Object) 移除指定元素(仅移除第一个)
        list.remove("kkk");
        System.out.println("list=>"+list);
        //remove(index) 移除指定位置元素
        list.remove(0);
        System.out.println("list=>"+list);
        //无法这样移除,因为list中没有list1这个元素
//        list.remove(list1);
//        System.out.println("list=>"+list);
        //removeAll(Collection)  移除所有Collection中含有的元素
        //将指定元素在指定位置添加到list中(1为下标,原来的list1长度为1,所以需要在下标为一处添加,
        // 也可直接添加(  add(object)  ),默认加到list1的尾部)
        list1.add(1,"test");
        list.removeAll(list1);
        System.out.println("list=>"+list);

        //set(index,object) 更新index位置元素为object
        list.set(0,"hhhh");
        System.out.println("list=>"+list);

        //subList(from,to)  切割原来的list并返回新的list  左闭右开  1 <= x  <2
        System.out.println("subList=>"+list.subList(1, 2));

        //将list转化为数组
        System.out.println("toArray()=>"+Arrays.toString(list.toArray()));

    }
}

三、ArrayLsit底层源码分析

一、没有初始化list的长度

1、先定义一个ArrayList实现List接口

 List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        //遍历list
        //增强器(底层也是使用迭代器实现)
        for(int i : list){
            System.out.println(i);
        }

2、Debug 进入new ArrayList()

进入debug前先将这条勾选取消,否则我们看不到为空的数据

在这里插入图片描述

进入构造函数

   /**
     * 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 = {};   
/**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {//帮我们创建一个空数组
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

跳出构造函数

进入Integer装箱

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

跳出Integer

进入add方法

size指的是当前真实list中所含有元素的数量
    public boolean add(E e) {
        //确认数组容量是否足够
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //将要添加的值赋值给elementData[size++]
        elementData[size++] = e;
        return true;
    }

进入ensureCapacityInternal方法

//size指的是当前真实list中所含有元素的数量
//minCapacity即为arraylist的size+1    
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

calculateCapacity 计算当前数组容量

    /**
     * Default initial capacity.
     */
    private static final int DEFAULT_CAPACITY = 10;   //ArrayList默认大小 

private static int calculateCapacity(Object[] elementData, int minCapacity) {//传入当前数组,及minCapacity(为size+1)
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//若elementData为空
            return Math.max(DEFAULT_CAPACITY, minCapacity);//返回DEFAULT_CAPACITY和minCapacity的最大值
        }
        //若数组不为空,则返回minCapacity
        return minCapacity;
    }

ensureExplicitCapacity

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;        //计数*此列表在结构上被修改的次数。结构修改是指改变结构尺寸的修改列表,
//或者以这样一种方式对其进行扰动,使得过程中的迭代可能产生错误的结果。


        //minCapacity是calculateCapacity方法计算后返回的容量     
        //elementData.length即为arraylist底层数组的容量
        if (minCapacity - elementData.length > 0) //判断arraylist的之前的size+1后,arrayList底层数组的容量是否够用
            grow(minCapacity);
    }

grow 扩容核心算法

    private void grow(int minCapacity) { 
        // overflow-conscious code
        //记录原数组长度
        int oldCapacity = elementData.length;
        //原数组长度+原数组长度右移一位(原数组除2,int型除完后向下取整)
        //即为扩容为原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //若新数组扩容后的长度比minCapacity小
        //处理当newCapacity为0的情况,给minCapacity默认赋值为10            
        if (newCapacity - minCapacity < 0)
            //将minCapacity的值赋值给newCapacity
            newCapacity = minCapacity;
        //newCapacity过大,超过MAX_ARRAY_SIZE时,报错
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        //将elementData扩容,并保留原来的元素
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

跳出grow

跳出ensureExplicitCapacity

跳出ensureCapacityInternal

回到add方法,经e添加到新的elementData中

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

成功添加第一个元素

这时默认将arraylist数组扩容为10

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u21VzNYu-1635388813251)(…/img/arraylist2.jpg)]

后续在数组容量小于等于10时,均不需要扩容

当数量大于10时,才需要再次扩容为原来的1.5倍

二、初始化了list的长度

 List<Integer> list = new ArrayList<Integer>(3);
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        //遍历list
        for(int i=0; i<list.size(); i++){
            System.out.println("o=>"+list.get(i));
        }

大体上基本一样

仅在构造函数时有所差别

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

四、总结(重点)

ArrayList 在未初始化长度的情况下,第一次将数组扩容为10
在初始化长度的情况下,则长度为初始化的长度

若数组长度不足,则扩容为原来的1.5倍(注意:扩容机制为int型,所以向下取整,15扩容为15+15/2=22)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值