ArrayList

作者: Jokerone_ | 来源:发表于2017-03-24 20:21 被阅读0次

ArrayList以数组的形式实现,顺序插入、查找快,插入、删除较慢(==寻址容易,插入删除困难==)
ArrayList的基本元素:

元素 作用
private transient Object[] elementData; ArrayList是基于数组的一个实现,elementData就是底层的数组
private int size; ArrayList里面元素的个数,这里要注意一下,size是按照调用add、remove方法的次数进行自增或者自减的,所以add了一个null进入ArrayList,size也会加1

四个关注点在ArrayList上的答案

关注点 结论
ArrayList是否允许空 允许
ArrayList是否允许重复数据 允许
ArrayList是否有序 有序
ArrayList是否线程安全 非线程安全

ArrayList的优点:

  1. ArrayList底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找也就是get的时候非常快
  2. ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已
    ArrayList的缺点:
  3. 删除元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能
  4. 插入元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能

因此,==ArrayList比较适合顺序添加、随机访问的场景==。

注意两个问题:

  1. ArrayList和Vector的区别
  2. 为什么ArrayList的elementData是用transient修饰的?
1、 容器默认大小为10,位置不够了自动扩增,每次增加当前长度的一半;(扩增时用Arrays.copyOf进行扩增)
2、 数组容量扩增到Integer.MAX_VALUE-8的时候,就会开始限制数组扩充,超过Integer.MAX_VALUE的时候,抛内存溢出异常;
3、 clone是浅拷贝,List中的引用指向的还是相同数据;
4、 线程不安全的;
5、 迭代器中的expectedModCount和modCount:迭代器初始化时,会用modCount去初始化expectedModCount,在迭代器的操作中都要检查这两个值的等值性,不想等抛出ConcurrentModificationException异常表示当前List正在被修改,为什么呢?如下:
List本身的add和remove操作时都会修改modCount的值,如果在迭代器循环迭代过程中调用了List本身的add和remove方法就会导致两个值不想等而抛出异常,而迭代器本身的remove则不会有这个问题,它会在remove完成后重新更新一遍expectedModCount保持两个值的等值性。
6、 ListIterator和普通迭代器类似,只是多了双向迭代的功能;
7、 ArrayList本身的sort其实是调用Arrays.sort传入比较器实现的

ArrayList自定义源码如下:

package com.hao.laker.study.javabase.source;

import java.util.Arrays;

/**
 * 自定义数组
 * Created by haojiahong on 17/3/1.
 */
public class MyArrayList<E> {
    private int capacity = 10;
    private int size = 0;
    private Object[] tables;

    public MyArrayList() {
        tables = new Object[capacity];
    }

    public MyArrayList(int capacity) {
        this.capacity = capacity;
        tables = new Object[capacity];
    }

    public void add(E e) {
        if (size >= capacity) {
            enlargeCapacity();
        }
        tables[size] = e;
        size++;
    }

    public void remove(int index) {
        if (index >= size) {
            throw new RuntimeException("the " + index + " is out of bond");
        }
        for (int i = index; i < size - 1; i++) {
            tables[i] = tables[i + 1];
        }
        tables[size - 1] = null;//垃圾回收
        size--;
    }

    @SuppressWarnings("unchecked")
    public E get(int index) {
        if (index >= size) {
            throw new RuntimeException("the " + index + " is out of bond");
        }
        return (E) tables[index];

    }

    /**
     * 数组扩容方法
     */
    private void enlargeCapacity() {
        capacity = capacity * 3 / 2 + 1;
//        Object[] newTables = new Object[capacity];
//        System.arraycopy(tables, 0, newTables, 0, tables.length);
        Object[] newTables = Arrays.copyOf(tables, capacity);
        tables = newTables;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append(tables[i]).append(",");
        }
        if (size > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("]");
        return sb.toString();
    }

    public static void main(String[] args) {
        MyArrayList<Integer> myArrayList = new MyArrayList<>();
        //添加操作
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        System.out.println(myArrayList.toString());
        //删除操作
        myArrayList.remove(2);
        System.out.println(myArrayList.toString());
        //get操作
        System.out.println(myArrayList.get(0));

    }

}

相关文章

网友评论

      本文标题:ArrayList

      本文链接:https://www.haomeiwen.com/subject/nrfqottx.html