ArrayList

Posted laurarararararara

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList相关的知识,希望对你有一定的参考价值。

ArrayList实现类:ArrayList是List接口的实现类

基本特点:
数据插入有序
可以存储null值
数据可以重复
底层的数据结构是数组

ArrayList的继承关系:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

继承AbstractList类,实现List接口;

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

AbstractLiST继承AbstractCollection类,实现List接口;

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

AbstractCollection实现Collection接口;

public interface Collection<E> extends Iterable<E>

Collection继承Iterable类;

public interface Iterable<T> {
    /**
     * Returns an iterator over elements of type {@code T}.
     *
     * @return an Iterator.
     */
    Iterator<T> iterator();
   }

Iterable是一个接口;

技术图片

 

相关属性:

    private static final int DEFAULT_CAPACITY = 10;//默认容量是10

    private static final Object[] EMPTY_ELEMENTDATA = {};

    private static final Object[] DEFAULTCAPACITY_EMPTY_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

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;
transient关键字:Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。
 作用:
        Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

 扩容机制:  数组的扩容是按照原数组长度的1.5倍扩容     

 /**
     * 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
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);  //>>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);
    }

得到该元素:

/**
     * Returns the element at the specified position in this list.
     *
     * @param  index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public E get(int index) {
        rangeCheck(index);

        return elementData(index);
    }

 

清空数组:clear

public void clear() {
        modCount++;

        // clear to let GC do its work垃圾回收器
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }

删除:因为ArrayList中可以存储值为null的元素,所以需要对null进行特殊判断

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

fastRemove的实现:主要将index+1号以后的元素移动到index号元素

 private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

arraycopy源码:

    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

 

1.自定义实现ArrayList

package Lesson1;
import java.util.Arrays;
/**
 * 问题:my.size()方法不等于elementData-1   elementData.length等于构造函数初始化时,传入的capacity,
 * 所以mysize()方法与elementData.length无关。所以getSize()方法的返回值可以直接为size
 * 自定义实现ArrayList
 * @param <T>
 */
public class ArrayListMyself <T>{
    private Object[] elementData;//定义了一个数组
    private int size;
    public ArrayListMyself(int capacity){
         elementData=(T[])new Object[capacity];
    }
    public ArrayListMyself(){
        this(2);
    }
    /**
     * 添加值为value的元素
     */
    public boolean add(T value) {
        if(full()){
            Arrays.copyOf(elementData,elementData.length*2);
        }
        this.elementData[this.size++]=value;
        return true;
    }
    public boolean full() {
      return this.elementData.length==this.getSize();
    }

    /**
     *
     * @return直接返回长度size
     */
    public int getSize(){
        return size;
    }

    /**
     * 获取index号元素 ,返回元素的值
     */
    public T get(int index) {
        if(index<0 || index>size){
            throw new IndexOutOfBoundsException("参数异常");
        }
        for (int i=0;i<elementData.length;i++){
           if(i==index){
               return (T)elementData[i];
           }
        }
        return null;
    }

    /**
     * 删除index号元素
     */
    public boolean remove(int index) {
        if(index<0 ||index>size){
            return false;
        }else {
            for (int i=index;i<size-1;i++){
                elementData[i]=elementData[i+1];
            }
            size--;

        }
        return true;
    }

    public static void main(String[] args) {
        ArrayListMyself my=new ArrayListMyself();
        my.add(4);
        my.add(5);
        System.out.println(my.size);//2
        System.out.println(my.elementData.length);//2
        System.out.println(my.remove(1));//true
        System.out.println(my.getSize());//1
        System.out.println(my.remove(0));//true
        System.out.println(my.size);//0

        if (my.size!=0){
           for (int i = 0; i <my.size; i++) {
            System.out.print(my.get(i)+" ");
          }
        }else {
            System.out.println("当前数组为空!");
        }

    }

}

或者可以自己写一个tooString方法,实现数组的打印:

public String tooString(){
        StringBuilder s=new StringBuilder();
        if(this.size==0){
            return null;
        }
        else {
            for (int i = 0; i < this.size; i++) {
                s = s.append(get(i) + " ");
            }
            return s.toString();
        }
    }

可以封装一个方法进行参数的检查,在添加或者删除的时候直接调用该方法:

(源码中给出了专门添加元素的方法rangeCheckForAdd)

   private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

 

技术图片

 

 2.

以上是关于ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

获取 Intent 片段上的 Serializable ArrayList

包含不同片段的HashMap(或ArrayList)

面试常用的代码片段

回收站视图未显示在片段中

从ViewPager android替换片段

无法更新FragmentPagerAdapter中的片段