JavaSE基础知识学习-----集合之ArrayList

ArrayList

首先明确的是:Collection的子接口是List接口,Listc存储的是有序可重复的元素,ArrayList是List接口的主要实现类,List接口的主要实现类有:

1.ArrayList

由数组方式实现数据存储,当然数组的访问速度比链表快。源码如下:

public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer.
 */
private transient Object[] elementData;

2.LinkedList

由连接实现数据的存储,随机添加和删除元素的的操作的效率要高于数组,简单说就更适用于频繁的插入和实现操作。

3.Vector

是一种古老的实现类,在Vector类中,里面的方法添加了synchronized修饰,是线程安全的,关于线程的相关知识会在后续的学习中,他的性能比ArrayList差,用的地方比较少,

ArrayList常用方法

ArrayList常用的方法和Collection基本一样,也大致看看吧,就当复习吧。

1.add("AA");向集合中添加一个元素
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
}
2.add(2, "CC");将指定的元素插入此列表中的指定位置。索引从0开始
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BB");
    list.add("DD");
    System.out.println(list);
    list.add(2, "CC");
    System.out.println(list);
}

结果为:

[AA, BB, DD]
[AA, BB, CC, DD]
3.addAll(list2);将形参中的集合元素全部添加到当前集合中的尾部。
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BB");
    list.add("DD");
    List<String> list2 = new ArrayList<String>();
    list2.add("CC");
    list2.add("EE");
    list.addAll(list2);
    System.out.println(list);
}

结果为:

[AA, BB, DD, CC, EE]
4.addAll(2, list2);将形参中集合元素添加到当前集合指定的位置。
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BB");
    list.add("DD");
    List<String> list2 = new ArrayList<String>();
    list2.add("CC");
    list2.add("EE");
    list.addAll(2, list2);
    System.out.println(list);
}

结果为:

[AA, BB, CC, EE, DD]
5.clear();清空当前集合中所有元素
list.clear();

注意:以下方法和Collection一样,都依赖元素对象的equals方法。更多的时候都需要重写equals方法。

6.contains("aa");返回当前 元素是否包含某一个对象。当前放回false。
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BB");
    list.add("DD");
    boolean contains = list.contains("aa");
    System.out.println(contains);
}
7.get(1);获取当前集合中指定位置的元素,这里返回BB
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BB");
    list.add("DD");
    String string = list.get(1);
    System.out.println(string);
}
8.indexOf("BB");返回当前集合中首次出现形参对象的位置,如果集合中不存在就返回-1.
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("AA");
    list.add("BB");
    list.add("BB");
    int indexOf = list.indexOf("BB");
    System.out.println(indexOf);
}

简单的方法就查询jdkAPI文档吧,下面做简要的说明:

1.size();放回当前集合元素个数.
2.isEmpty();判断集合是否为空,返回布尔类型的结果。
3.lastIndexOf(Object o);返回集合中最后一次出现形参元素的索引,不存在就返回-1。
4.toArray();将集合转换为数组
5.set(int index,E element);用指定元素替代集合中指定位置的元素。
6.remove(Object o);移除集合中首次出现的元素。
7.remove(int index);移除集合中指定位置的元素。

ArrayList实现原理(源码解读)

ArrayList是List接口的可变数组的实现,允许包括null在内的所有元素,既然是数组,那么该类肯定会存在改变存储列表的数组大小的方法。
每一个ArrayList实例都有一个容量,该容量是用来存储列表元素的数组的大小,他总是等于列表的大小,随着往ArrayList中添加元素,这个容量也会相应的总动增长,自动增长就会带来数据向新数组的重新拷贝。

1.底层使用数组实现

 private transient Object[] elementData;

2.构造方法如下:

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

在初始化ArrayList实例时,可以构造一个初始容量为10的空列表,也可以构造一个指定初始容量的空列表以及构造一个包含指定Collection元素的列表。

3.如何实现存储的?

3.1使用set(int index, E element) ;方法,用指定的元素替代指定位置的元素
  public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
3.2add(E e);将指定的元素添加到集合尾部
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
3.3add(int index, E element)将指定的元素插入此列表中的指定位置
public void add(int index, E element) {  
    if (index > size || index < 0)  
        throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);  
    // 如果数组长度不足,将进行扩容。  
    ensureCapacity(size+1);  // Increments modCount!!  
    // 将 elementData中从Index位置开始、长度为size-index的元素,  
    // 拷贝到从下标为index+1位置开始的新的elementData数组中。  
    // 即将当前位于该位置的元素以及所有后续元素右移一个位置。  
    System.arraycopy(elementData, index, elementData, index + 1, size - index);  
    elementData[index] = element;  
    size++;  
}  

4.如何读取元素?

  public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

5.删除元素

 public boolean remove(Object o) {
    if (o == null) {
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}

注意:从集合中移除一个元素,如果这个元素不是最后一个元素,那么这个元素的后面元素会想向左移动一位。

5.如何实现扩容的?

 public void ensureCapacity(int minCapacity) {
    if (minCapacity > 0)
        ensureCapacityInternal(minCapacity);
}
 private void ensureCapacityInternal(int minCapacity) {
    modCount++;
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
 private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

从上面的代码可以看出,数组进行扩容时,会将老数组的所有元素拷贝到新数组中,
其中新数组的大小是老数组大小右移一位再加上老数组的大小。

6.手动调整底层数组的容量为列表实际元素大小的方法

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

推荐阅读更多精彩内容

  • 接着Java集合框架学习---深入探究ArrayList源码(一)继续学习ArrayList源码。 ensureC...
    EakonZhao阅读 1,168评论 0 3
  • Java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位...
    聂叼叼阅读 493评论 0 2
  • 我颓废的时候,你在悄悄的长肉。总想对你说些什么,好多次都拨不出那个电话。恍然间明白我们之所以是朋友,就是我有...
    木兮日记阅读 144评论 0 0
  • 摆脱了高中语文老师灌输的死板的高分作文格式,提起笔来竟没有减轻些许负担,更使这笔触变得沉重,仿佛在为逝去的时光哀悼...
    叫我坏坏阅读 428评论 0 1
  • ** 根据Teal Swan文章翻译 生活中总是有一些状况不是我们能控制的,我们不能“做”任何事情来改变这些状况,...
    崔琪臻心灵疗愈师阅读 2,070评论 0 2