`
iamxi
  • 浏览: 191822 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Java源码解读——ArrayList(一)

阅读更多

为了提高自己的Java开发能力,我也向高手、牛人学习,去解读源码。自己底子差了点,不过看个源码还是没问题的。第一站ArrayList。

源码为Java 1.7的源码

ArrayList是一个实现可变长数组,继承AbstractList类,实现所有的List接口,还实现了RandomAccess、Cloneable、Serializable接口。ArrayList不进行同步,除此之外基本和Vector等同。

 

1、成员变量

 

private transient Object[] elementData;

elementData用于保存数据的数组。

 

private int size;

 size为ArrayList内的数据数量,但并不是elementData的长度。

 

2、构造方法

    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }

    public ArrayList() {
        this(10);
    }

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

  第一个是根据指定长度建立List,第二个是根据默认长度建立List,第三个根据传入Collection子类实例创建List。通过第三个实例看到Collection子类都会实现toArray()方法,可以看出至少很多Collection子类依赖于数组来实现(还没看过其他的集合实现,这只是我的妄言而已)。

 

3、add方法

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

 该方法在数组最后添加一个元素。ensureCapacityInternal方法提供了ArrayList的自增长实现,以确保elementData有足够的长度来容纳新进入的元素(后面介绍自增长的实现)。

 

    public void add(int index, E element) {
        rangeCheckForAdd(index);

        ensureCapacityInternal(size + 1); 
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

 该方法是在第i个位置插入一个元素。rangeCheckForAdd方法用于检查index是否越界,代码如下:

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

System.arraycopy方法使用native修饰符(这个修饰符第一次看到,谷歌了下,大致是说这个修饰的方法是通过底层实现的),效率自然高。arraycopy如果对同一个数组进行操作时,会首先把从源部分拷贝到一个临时数组,在把临时数组的元素拷贝到目标位置。值得注意的是,如果数组内不是基本类型,System.arraycopy的拷贝过来的也只是个引用而已。

 

4、remove方法

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

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null;

        return oldValue;
    }

 删除指定位置的元素,并返回删除的元素。以前还真没注意过删除时候还返回删除的元素。rangeCheck方法用于检查越界,代码如下:

    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

  modCount用于记录ArrayList的结构性变化的次数,add()、remove()、addall()、removerange()及clear()方法都会让modCount增长。add()及addall()方法的对modCount的操作在ensureCapacityInternal中。

numMoved用于检查删除的元素是否是最后ArrayList的最后一个元素(不一定是数组elementData的最后一个)。如果不是最后一个,则用arraycopy移动数组,最后将数组size-1处赋值为空。

 

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

 删除与Object o相同的第一个元素。这里fastRemove方法,从代码来看和remove(int 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;
    }

 

5、addAll方法

   //将Collection c内的数据插入ArrayList中
   public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    //将Collection c中的数据插入到ArrayList的指定位置
    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

这两个方法都会调用ensureCapacityInternal方法使数组能够容纳下新的数据。后一个方法会判断是否是在数据最后插入,如果是则和第一个方法相同,如果不是,则先使用arraycopy移动数组。

 

6、removeAll和retainAll

删除或保留ArrayList中包含Collection c中的的元素,这两个方法都依赖batchRemove(Collection<?> c, boolean complement)实现。

 

7、get和set

前者是获取元素,后者是替换某个位置上的元素,然后返回被替换的元素。这两个都用rangeCheck做越界检查。set方法不进行自增长,也就说替换的元素必须是size内的。

 

 

 

发现感觉快把源码复制过来了。唉,以后不能这么写

分享到:
评论

相关推荐

    Java源码解析——看优秀源码最能使人进步

    Java源码解析——看优秀源码最能使人进步 Java源码解析是一种深入了解JDK源码的方式,适合那些想深入了解JDK源码的人。通过对JDK源码的解析,可以让开发者更好地理解Java语言的底层逻辑,从而写出更加高效、稳定的...

    java——ArrayList-源码解析.docx

    ArrayList 是 Java 中常用的集合类,它是 List 接口的一个实现,基于数组进行操作。ArrayList 的设计使得元素可以动态地添加和删除,同时提供了对数组大小的灵活调整。它实现了 ICollection 和 IList 接口,提供了...

    Java源码篇之容器类——ArrayList

    在Java编程语言中,ArrayList是集合框架中一个重要的容器类,属于List接口的实现,它提供了动态数组的功能。本文将深入解析ArrayList的源码,帮助开发者理解其内部工作原理。 1、前言 在日常开发中,ArrayList是...

    清华妹子的Java仓库(进阶学习路线)

    Java集合框架源码解读(1)——ArrayList、LinkedList和Vector Java集合框架源码解读(2)——HashMap Java集合框架源码解读(3)——LinkedHashMap Java集合框架源码解读(4)——WeakHashMap Java集合框架源码解读

    java基础——————试题库

    这份“java基础——————试题库”资源旨在帮助学习者系统地复习和深入理解Java的基础知识,确保他们能够全方位地掌握这一强大的编程工具。下面将详细阐述Java的基础知识点。 1. **Java简介** - Java是由Sun ...

    JAVA学习笔记————————

    在深入探讨JAVA学习笔记之前,我们首先理解一下JAVA这一编程语言的重要性。JAVA,由Sun Microsystems公司(现已被Oracle收购)于1995年推出,是一种面向对象的、跨平台的编程语言,以其“一次编写,到处运行”的特性...

    java源码解读-JavaSource:Java源码解读

    在Java编程语言的世界里,源码解读是提升技术深度、理解内部机制的关键步骤。"JavaSource:Java源码解读"项目旨在帮助开发者深入探索Java的内部工作原理,从而更好地运用和优化代码。在这个项目中,我们可以看到一...

    java源码解读-java-src:java源码解读

    Java源码解读是Java开发人员深入理解平台工作原理和编程模型的重要途径。在这个"java-src:java源码解读"项目中,我们可以探索Java的核心库,包括JVM(Java虚拟机)、集合框架、并发机制、I/O流、网络编程等多个关键...

    尚硅谷Java基础实战——Bank项目下载地址

    5. 集合框架:ArrayList、LinkedList、HashMap等是Java集合框架的一部分,它们用于存储和管理对象。在Bank项目中,可以使用集合来存储多个账户或客户信息,便于管理和查找。 6. IO流:Java的IO流用于读写数据。在...

    java源码文档src

    `java.text`和`java.util.Locale`包提供了国际化和本地化的支持,源码解读能帮助开发者为不同地区和语言的用户提供定制服务。 总之,Java源码文档src是Java开发者不可或缺的学习资源,它揭示了Java平台的内在工作...

    ArrayList源码分析

    ArrayList是Java集合框架中的一员,它是List接口的一个实现,提供了动态数组的功能。ArrayList的主要特点是它在内存中以数组的形式存储元素,因此对于随机访问元素,它的性能非常高效。本篇文章将深入探讨ArrayList...

    Java学习笔记——良葛格

    "Java学习笔记——良葛格"是一份专为初学者设计的教程资料,由良葛格精心编写,旨在帮助读者掌握JDK5.0版本的Java基础知识。JDK(Java Development Kit)是Java开发的核心工具集,包含了编译器、调试器和运行环境等...

    Java日程管理——万年行事历源代码

    本项目"Java日程管理——万年行事历源代码"提供了一个完整的解决方案,覆盖了从基本的日程创建到复杂的日历视图展示。下面我们将深入探讨这个项目中的关键知识点。 1. **Java基础**:此项目基于Java语言实现,这...

    java大学教程——课件

    总的来说,这份"Java大学教程——课件"涵盖了从基础到进阶的全面内容,对于希望进入Java编程领域的初学者来说,是一份非常宝贵的资源。通过系统学习和实践,初学者可以逐步建立起坚实的Java编程技能,并为未来更复杂...

    java毕业设计之ArrayList,LinkList链表接口实现源码.zip

    在本Java毕业设计项目中,主要探讨了两种重要的数据结构——ArrayList和LinkedList,它们都是Java集合框架中的核心组件,属于List接口的实现类。ArrayList和LinkedList各有特点,适合不同的应用场景,理解并掌握这两...

    Java源码大全

    Java源码大全是一个集合了各种Java编程基础知识和经典算法的资源包,对于Java初学者以及有一定经验的开发者来说,都是一个宝贵的参考资料。这个压缩包涵盖了Java语言的不同方面,旨在帮助学习者深入理解Java编程的...

    java源码下载,java

    在学习Java源码时,还可以研究其标准库(JDK)中的类,如`java.lang.String`、`java.util.ArrayList`等。这些类是Java语言的基础,它们的实现往往体现了设计模式和最佳实践。 为了更好地理解和学习Java源码,可以...

    Java毕业设计——学校管理系统设计与实现(源码+数据库).zip

    《Java毕业设计——学校管理系统设计与实现》是一个典型的软件工程实践项目,主要涵盖了Java编程语言、数据库管理和Web应用开发等多个领域的知识。以下是该项目可能涉及的关键技术点和知识点的详细解析: 1. **Java...

    Java小程序——山区果园

    【Java小程序——山区果园】是一款基于Java GUI(图形用户界面)技术开发的应用程序,主要针对初学者设计,旨在帮助他们理解和实践Java编程语言中的GUI编程。这个小程序通过模拟山区果园的场景,提供了一个互动的...

Global site tag (gtag.js) - Google Analytics