`
wdhdmx
  • 浏览: 302980 次
  • 性别: Icon_minigender_1
  • 来自: 山西
博客专栏
D4bbb5f7-9aa4-3e66-8194-f61b3f0241c2
天天编程
浏览量:21815
社区版块
存档分类
最新评论

ArrayList源码理解

阅读更多

构造方法:

     这个类中有一个Object[]的对象来存储数据,代码是:

this.elementData = new Object[initialCapacity];//存储对象的数组
 

    initialCapacity默认是10,这个elementData定义的时候用transient定义,不知道什么意思。size为集合的长度int。默认没有给值,所以是0。
    构造方法:

public ArrayList(int initialCapacity) {
        this.elementData = new Object[initialCapacity];
}

    构造方法:

public ArrayList() {
        this(10);
}
 

    在构造方法中

public ArrayList(Collection<? extends E> c) {
          //返回一个Object[]的副本对象(大部分是这样),长度会是内部变量的长度size,而不是这个Object[]的长度
            elementData = c.toArray();
            size = elementData.length;
            //这里验证内部的值是否是Object[],然后依情况转成Object类型
            if (elementData.getClass() != Object[].class)
                 //这里复制出来的Onject[]值所占空间为size,内部变量的数目也是size
                elementData = Arrays.copyOf(elementData, size, Object[].class);
}

      在这个构造方法中会将c中的值转为Object[]类型,在c.toArray()中,一般会传出一个对象的副本,即利用copy传出elementData的数据。所以这里很有可能是复制了两次数据。

add方法

     返回的是否添加成功。注意,这里面竟然可以添加null值。

public boolean add(E e) {
    //增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
    ensureCapacity(size + 1); 
    //复制后size+1
    elementData[size++] = e;
    return true;
 }

    类中的E泛型 不过都会当成Object处理??
    上面的第一句代码:

public void ensureCapacity(int minCapacity) {
                        //不知道这句是干什么的?????????????????????
                        modCount++;
                        //获取当前数组长度,而并不是内部拥有的变量size
                        int oldCapacity = elementData.length;
                        //如果总空间不够的话
                        if (minCapacity > oldCapacity) {
                               
                            Object oldData[] = elementData;
                            //开辟1.5倍+1的空间
                            int newCapacity = (oldCapacity * 3)/2 + 1;
                            //如果依然不够的话,直接开辟minCapacity的空间
                        if (newCapacity < minCapacity)
                                        newCapacity = minCapacity;
                                //将数据复制到新的数组中
                        elementData = Arrays.copyOf(elementData, newCapacity);
         }
} 

      add(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); 
         //复制index后size-index长度的值到index+1的位置上,就是将index后面的内容向后移动一位,把index这个位置空出来
         System.arraycopy(elementData, index, elementData, index + 1,size - index);
        //赋值
        elementData[index] = element;
        //大小+1
        size++;
}

 

public boolean addAll(Collection<? extends E> c) {
		Object[] a = c.toArray();
		//a.length 相当于复制过来c的size。这里也是数组所占空间
 		int numNew = a.length;
		ensureCapacity(size + numNew); 
		//将加入的a复制到size之后,注意这里都是数组的位置,
		System.arraycopy(a, 0, elementData, size, numNew);
		//更新size
		size += numNew;
		//这个很有特色,按照添加的长度来判断是否成功。很危险
		return numNew != 0;
}
 
public boolean addAll(int index, Collection<? extends E> c) {
		if (index > size || index < 0)
		    throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
		Object[] a = c.toArray();
		int numNew = a.length;
		ensureCapacity(size + numNew); 
		int numMoved = size - index;
		//这里是判断是否需要系统,如果index 和size一样大的话就复制移动了。
		if (numMoved > 0)
		    System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
		System.arraycopy(a, 0, elementData, index, numNew);
		size += numNew;
		return numNew != 0;
}	

 

get方法

 

public E get(int index) {
	//范围检查
	RangeCheck(index);	
	//竟然会强转,不过想想也很正常。
	return (E) elementData[index];
}			
//只是做了一个越界检查
private void RangeCheck(int index) {
	if (index >= size)
	    throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
}		

 

size方法

 

public int size() {
        //直接返回size的值。
	return size;
}	

 

clear方法

public void clear() {
	//这里又不知道在干什么
	modCount++;
	//看来数组的空间不会改变,内部的变量都清空了。
	for (int i = 0; i < size; i++)
			//所有的值赋了空值。
	    elementData[i] = null;
	size = 0;
}		

remove方法        

    返回删除对象

public E remove(int index) {
 	//判断是否越界
		RangeCheck(index);
		  //这里又不知道在干什么
		modCount++;
		//强转
		E oldValue = (E) elementData[index];
		//看是否需要复制移动
		int numMoved = size - index - 1;
		if (numMoved > 0)
		    System.arraycopy(elementData, index+1, elementData, index,numMoved);
		elementData[--size] = null; 
		//返回
		return oldValue;
}		

 

    返回是否删除成功

public boolean remove(Object o) {
 //第一步直接把对象强转为Object类型了。
		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++)
	   	 			//注意这里判断的删除只是equals相同就行,这个地方很有奇异,
						if (o.equals(elementData[index])) {
						    fastRemove(index);
						    //只会删除碰到的第一条相同对象
						    return true;
						}
       	}
   //没找到会返回false。
	return false;
}
 

 

   快速删除

private void fastRemove(int index) {
 	//又是这个神秘的变量
  modCount++;
  //和上面的删除是一个人写的,一样。
  int numMoved = size - index - 1;
  if (numMoved > 0)
      System.arraycopy(elementData, index+1, elementData, index, numMoved);
  //size-1
  elementData[--size] = null;
}

 

   ArrayList里面的removeAll是调用的下面class的方法。

   AbstractCollection.class

 public boolean removeAll(Collection<?> c) {
			boolean modified = false;
			Iterator<?> e = iterator();
			while (e.hasNext()) {
					//包含的方法下面会看到。
			    if (c.contains(e.next())) {
				e.remove();
				//这里是删除所有的
				modified = true;
			    }
			}
			return modified;
  }

 public boolean retainAll(Collection<?> c) {
			boolean modified = false;
			Iterator<E> e = iterator();
			while (e.hasNext()) {
			    if (!c.contains(e.next())) {
			 //   不包含的关系,就是几乎会删除掉原对象中所有的值
				e.remove();
				modified = true;
			    }
			}
			return modified;
  }

 

indexOf方法     

 

public int indexOf(Object o) {
	if (o == null) {
	    for (int i = 0; i < size; i++)
	    //在size之前找到空,会返回,超过size后没用
		if (elementData[i]==null)
		    return i;
	} else {
	//依然只是比较equals方法。
	    for (int i = 0; i < size; i++)
		if (o.equals(elementData[i]))
			//只返回查找的第一个。
		    return i;
	}
	//找不到返回 int -1
	return -1;
}
 

 

lastIndexOf方法

    lastIndexOf(Object o)
    返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
    和index一样,只是这个循环从最后一个开始,向前循环。所以查找的是最后一个。

toArray方法

 

public Object[] toArray() {
	//返回一个数组,数组空间和变量同样大小的。
	return Arrays.copyOf(elementData, size);
}

    未定义泛型的时候Object[] 不能强转成 E[] ,

trimToSize方法

    将此 ArrayList 实例的容量调整为列表的当前大小

public void trimToSize() {
		//未知
		modCount++;
		int oldCapacity = elementData.length;
		if (size < oldCapacity) {
	            elementData = Arrays.copyOf(elementData, size);
		}
}

 

set方法

     E set(int index,E element)
     就是将对应未知的变量换成新的,将旧的值返回,当然先是对越界做过滤。

isEmpty方法

 

isEmpty() 
 	public boolean isEmpty() {
	return size == 0;
}

    代码更容易懂。

contains方法

    如果此列表中包含指定的元素,则返回 true。

public boolean contains(Object o) {
	return indexOf(o) >= 0;
}

public boolean containsAll(Collection<?> c) {
	Iterator<?> e = c.iterator();
	while (e.hasNext())
  	if (!contains(e.next()))
			return false;
		return true;
} 

   这里是不讲究顺序,只要c中的变量都有就行。例如:a={1,3,2,4},b={1,3,3} 这里,a包含b。

               

clone方法

     克隆被覆写

public Object clone() {
		try {
		    ArrayList<E> v = (ArrayList<E>) super.clone();
		    v.elementData = Arrays.copyOf(elementData, size);
		    v.modCount = 0;
		    return v;
		} catch (CloneNotSupportedException e) {
		    // this shouldn't happen, since we are Cloneable
		    throw new InternalError();
		}
}	
 

       
  好了ArrayList 就算看完了。

分享到:
评论

相关推荐

    ArrayList源码分析

    ArrayList是Java集合框架中的一员,它是List...通过深入学习ArrayList的源码,我们可以更好地理解其工作原理,从而在实际开发中做出更优的选择,提升程序的效率和稳定性。同时,这也是提升Java编程技能的一个重要步骤。

    ArrayList源码分析(含jdk1.8).pdf

    通过以上对ArrayList源码的分析,可以总结出如下关键知识点: 1. ArrayList的实现基于动态数组,可以动态地进行容量的调整; 2. ArrayList具有默认初始化容量10,以及无参构造时延迟初始化的特性; 3. ArrayList...

    ArrayList源码.zip

    本压缩包文件“ArrayList源码.zip”包含ArrayList的源代码,可以帮助我们深入理解其内部工作原理和优化策略。 ArrayList的核心实现是通过一个Object类型的数组来存储元素。当添加元素时,如果当前容量不足,...

    第二章 ArrayList源码解析1

    第二章 ArrayList源码解析 ArrayList是Java集合框架中的一种动态数组,它继承自AbstractList,并实现了List接口。ArrayList主要用于存储可变大小的对象列表,它的核心是通过一个Object类型的数组elementData来实现...

    硬核ArrayList源码分析,答应我每天看一遍好么

    《硬核ArrayList源码分析——深入理解Java集合框架》 ArrayList是Java集合框架中的一个重要组成部分,它是基于动态数组实现的列表。在Java 1.8版本中,ArrayList的实现细节和内部工作原理对于理解其性能和行为至关...

    ArrayList源码分析.docx 等

    转换为其内部数组 `elementData`,然后根据转换后的数组长度设置 `size`。这里需要注意的是,如果 `c.toArray()` ...在面试中,深入理解 ArrayList 的源码和其与其他数据结构的区别是展示 Java 基础技能的重要方面。

    Java 集合框架(2-9)-Collection - ArrayList 源码解析.pdf

    《Java集合框架(2-9)-Collection - ArrayList 源码解析》 ArrayList是Java集合框架中的一个重要组件,它属于List接口的实现类,提供了一种动态数组的逻辑视图。ArrayList以高效、灵活的方式存储和操作对象序列,是...

    Java编程中ArrayList源码分析

    Java编程中ArrayList源码分析是Java编程中一个重要的知识点,对于Java开发者来说,了解ArrayList的源码可以帮助他们更好地理解Java集合框架的实现机制,从而提高自己的编程水平。 以下是ArrayList源码分析的主要...

    ArrayList源码解析(数据结构及底层实现)(csdn)————程序.pdf

    ArrayList 是 Java 中常用的动态数组,它是 List 接口的一个实现,允许我们在列表的任何位置插入...通过了解 ArrayList 的源码,我们可以更好地理解和优化在实际项目中使用 ArrayList 的方式,以提高代码的效率和性能。

    Java集合框架ArrayList源码分析(一)

    《深入剖析Java集合框架ArrayList源码》 Java集合框架中的ArrayList是开发者常用的数据结构,它是一种基于动态数组实现的列表。ArrayList的特点在于它的内部结构、性能优化以及在并发环境下的处理方式。本文将深入...

    关于 ArrayList get(0)的异常JDK源码跟进

    通过阅读和分析JDK源码,我们可以深入理解ArrayList的工作原理,这对于排查和解决实际问题非常有帮助。在遇到类似问题时,可以先检查索引是否合法,再检查ArrayList是否已添加元素,最后结合源码分析异常产生的具体...

    ArrayList动态删除 自定义Adapter (附源码)

    ArrayList动态删除与自定义Adapter是Android开发中的常见操作,它涉及到数据存储、用户界面更新以及适配器模式的运用。...通过阅读和分析提供的源码,可以进一步加深对这一机制的理解,并应用于实际项目中。

    ArrayList源码和多线程安全问题分析

    ArrayList源码和多线程安全问题分析 在 Java 编程语言中,ArrayList 是一个常用的集合类,它提供了动态数组的实现,能够存储大量的数据。但是,在多线程环境下,ArrayList 并不是线程安全的。这篇文章主要介绍了 ...

    ArrayList-LinkedList-源码.rar

    总的来说,理解ArrayList和LinkedList的源码有助于我们更好地利用这两种数据结构,根据具体需求做出更优的选择。通过深入学习源码,我们可以看到Java集合框架的精妙设计,提升我们的编程技巧和问题解决能力。

    java——ArrayList-源码解析.docx

    ArrayList 是 Java 中一种常用的列表类,它是 List 接口的实现,基于动态数组的数据结构。ArrayList 的核心特性在于其能够动态地调整数组的大小以适应元素数量的变化,从而...理解其内部机制有助于更好地优化代码性能。

    JDK1.6中Arraylist,Vector,LinkedList源码

    这里我们将深入探讨这三种数据结构的源码,理解它们的内部实现、性能特性和适用场景。 首先,ArrayList是基于动态数组实现的。它的内部是一个Object类型的数组,当添加元素导致容量不足时,会自动扩容。扩容策略...

    源码解析jdk7.0集合:ArrayList的底层实现原理.pdf

    在探讨 JDK 7.0 中 ArrayList 的底层实现原理之前,首先需要了解 ArrayList 作为 Java 集合框架中 List 接口的动态...此外,了解 ArrayList 的源码还有助于深入理解 Java 集合框架的设计哲学及面向对象设计的诸多原则。

Global site tag (gtag.js) - Google Analytics