ArrayList的学习笔记

ArrayList的继承和接口实现

1、ArrayList的简单介绍

  1. ArrayList是一个动态数组队列,它可自动扩容,每次扩容大小为原来的1.5倍,初始的默认值为10

private static final int DEFAULT_CAPACITY = 10;

  1. ArrayList底层是由Object数组构成

  2. ArrayList是线程不安全的,如果想使用线程安全的Arraylist可使用Collections.synchronizedList(List l)函数

  3. ArrayList对删除和添加(非两端)操作是具有昂贵时间花费的

  4. ArrayList对访问元素操作所花费的时间是常数的

Tips

ArrayList建议使用情况

①适用于需要多次访问数据

②经常在末端添加元素

2、ArrayList的构造函数

ArrayList提供三种构造函数

①public ArrayList(int initialCapacity)


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

    }

}

//声明的变量

transient Object[] elementData; // non-private to simplify nested class access

private static final Object[] EMPTY_ELEMENTDATA = {};  //默认为空

首先判断输入是初始值是否大于0,如果大于就直接开辟一个初始值大小的数组

如果等于0就直接把EMPTY_ELEMENTDATA的数组的地址赋予初始的elementData

②public ArrayList()


public ArrayList() {

    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

}

transient Object[] elementData; // non-private to simplify nested class access

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

当不填写初始值时,会直接把DEFAULTCAPACITY_EMPTY_ELEMENTDATA的地址赋予初始的elementData

但是上面说初始值是10,但是这里并没有出现10,这是为什么呢?

这就不得不介绍另一个函数 确定内部容量函数


private void ensureCapacityInternal(int minCapacity) {

        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {

            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

        }

        ensureExplicitCapacity(minCapacity);

    }

扩容函数是Arraylist的基础,上面很很幸免的写到,如果elementData的地址为DEFAULTCAPACITY_EMPTY_ELEMENTDATA的地址,就直接使用DEFAULT_CAPACITY(10)的容量

这里就很好解释了为什么ArrayList的初始默认值为10

③public ArrayList(Collection<? extends E> c)


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;

    }

}

创建一个包含collection的ArrayList,这个构造方法不是很常用,着重介绍一下后面的通配符

Collection<? extends E> c

①必须是Collection类型的

② ? extends E , ? 代表着任意的,extends很好理解就是继承,这个E代表着和AyyayList相同的数据类型

大家回忆一下这个类一开始


public class ArrayList<E> extends AbstractList<E>

        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

这个这个E实际上是和ArrayList<E>是相同的含义,必须是相同的数据类型

3、ArrayList的类继承关系

image

首先根据继承关系,一层一层推到出Arraylist的继承情况


public class ArrayList<E> extends AbstractList<E>

        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

①首先继承了AbstractList这个抽象类

②实现了List,RandomAccess,Cloneable,和序列化接口(java.io.Serializable)

Tips

1、什么是RandomAccess

答:RandomAccess接口实际上是一个标志性接口,你实现了这个接口代表你具有随机访问数据的能力(既通过数组下标直接访问数据)由此可知LinkedList肯定不会实现这个接口,因为它无法通过下标访问


public interface RandomAccess {

    //RandomAccess,java源码里面什么都没有

}

2、Cloneable接口的作用

答:Cloneable接口也是一个标记性接口,实现这个接口代表着你可被clone,能够使用Object.clone()方法


public interface Cloneable {

    //和上面的随机访问接口一样,不具有任何代码

}

3、什么是序列化

答:

把对象转换为字节序列的过程称为对象的序列化

把字节序列恢复为对象的过程称为对象的反序列化

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

2) 在网络上传送对象的字节序列。

通俗的来说就是ArrayList内的数据可以保存在你的硬盘上

4、什么是List接口

我们打开List接口的源码


public interface List<E> extends Collection<E>

一上来展示的就是List接口继承与Collection接口,那我们再翻到Collection接口


public interface Collection<E> extends Iterable<E>

这时我们发现,怎么还有接口,那么继续往上翻


public interface Iterable<T>

这下终于没有接口了,舒服了。。。。

这时我们发现 Iterable迭代器接口是ArrayList的顶级父类,这三个接口继承到底让List接口获得了那些功能呢

①Iterable接口


public interface Iterator<E> {

    /**

    * Returns an iterator over elements of type {@code T}.

    *

    * @return an Iterator.

    */

    Iterator<T> iterator();



    // 1.8新增了两个方法,暂不讨论

}

上面的代码说明表示会返回一个Iterator类型的变量

Iterator是迭代器接口,这就表明获得了一个迭代器

所以说,Iterable使List接口获得了迭代器功能

②Collection接口


public interface Collection<E> extends Iterable<E> {

    // Query Operations



    int size();

    boolean isEmpty();

    boolean contains(Object o);



    Iterator<E> iterator();

    <T> T[] toArray(T[] a);

    boolean add(E e);

    boolean remove(Object o);

    boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c);

    boolean removeAll(Collection<?> c);

    boolean retainAll(Collection<?> c);



    void clear();



    boolean equals(Object o);



    int hashCode();

}

Collection是List和set接口的父类,他提供了操作数据的基本方法名称

由此可知Collection使得List获得了基本操作方法的名称

③List接口

List接口继承了上述两个接口的所有特性,但是List接口代表着的是有序的Collection接口

即它用某种特定的插入顺序来维护元素顺序。用户可以对列表中每个元素的插入位置进行精确地控制,同时可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素

5、什么是AbstractList抽象类

我们首先打开AbstractList抽象类的源码


public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

到这里我们发现了一个我们熟悉的List接口,但是还没结束,继续翻


public abstract class AbstractCollection<E> implements Collection<E>

到这里呢,我们又见到了我们熟悉的Collection接口

那么问题来了,我们为什么要创建一个AbstractCollection抽象类呢?

在此呢,我们需要复习几个概念

①当一个类实现某一个接口时,必须要实现这个接口的所有方法

②当一个类继承某一个类时,可以重写也可以不重写父类的方法

③抽象类是具有抽象方法的类,有抽象方法的类一定是抽象类,没有抽象方法的类也可能是抽象类

④抽象类无法创建实例,必须被继承后重写抽象方法

答:当我们需要实现Collection接口时,我们必须重写Collection接口中的全部方法,而AbstractCollection则帮我们实习了大多数的方法,我们只需要重写其中的几个方法,即可完成Collection接口的使用

未实现的方法为


public abstract Iterator<E> iterator();

public abstract int size();

同理


public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

在AbstractList抽象类中,实现了List的大多数方法,只剩下几个必须要子类实现的函数没有实现

比如add(), set(),remove(),还有size()


public void add(int index, E element) {

    throw new UnsupportedOperationException();

}

如不重写add()方法就会抛出异常

那么到目前为止,我们发现了AbstractList抽象类继承了AbstractCollection抽象类

①AbstractCollection抽象类完成了Collection接口的基本方法但还保留了抽象方法等待子类去重写实现

②AbstractList抽象类进一步完善了AbstractCollection抽象类的方法,使得其变成了表结构,也就是说数据开始有序起来,在几个关键函数中AbstractList强制子类重写方法不然会爆出异常

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容