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

java ArrayList与Vector源码学习

    博客分类:
  • Java
阅读更多

Vector和ArrayList非常相似,两者都是用来表示可变数组,内部元素的存储都是通过数组来实现,可以随机的访问某个元素。

两者的主要区别是Vector的方法带有synchronized标志,各方法的访问是同步的,因此,Vector能够支持多线程,但是相应地效率比较低;ArrayList的方法没有synchronized标志,不是线程安全的。还有个比较小的差异是Vector在容量不够时,选择 size * 2扩容;ArrayList选择 size * 3/2 + 1扩容。

 

下面先来看下ArrayList的源码:

 

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

 RandomAccess: 这个是标记接口,没有需要实现的方法,声明ArrayList可以随机访问

Cloneable:ArrayList支持拷贝

Serializable: ArrayList支持序列化

 

ArrayList定义了如下的数组对象:

 

/**
     * 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;

 ArrayList使用elementData数组来缓存元素,使用transient关键字说明该数组对象不会被默认序列化,皱眉,开始很困惑,既然声明了ArrayList是可序列化的,为什么数组对象又声明为不能被序列化的?

 

 

 /**
     * Save the state of the <tt>ArrayList</tt> instance to a stream (that
     * is, serialize it).
     *
     * @serialData The length of the array backing the <tt>ArrayList</tt>
     *             instance is emitted (int), followed by all of its elements
     *             (each an <tt>Object</tt>) in the proper order.
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
	// Write out element count, and any hidden stuff
	int expectedModCount = modCount;
	s.defaultWriteObject();

        // Write out array length
        s.writeInt(elementData.length);

	// Write out all elements in the proper order.
	for (int i=0; i<size; i++)
            s.writeObject(elementData[i]);

	if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }

    }

/**
     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
	// Read in size, and any hidden stuff
	s.defaultReadObject();

        // Read in array length and allocate array
        int arrayLength = s.readInt();
        Object[] a = elementData = new Object[arrayLength];

	// Read in all elements in the proper order.
	for (int i=0; i<size; i++)
            a[i] = s.readObject();
    }

 因为ArrayList自定义了writeObject和readObject的方法,在writeObject中循环elementData数组序列化ArrayList中的元素。 可是为啥要这么折腾呢?

 

 public void ensureCapacity(int minCapacity) {
	modCount++;
	int oldCapacity = elementData.length;
	if (minCapacity > oldCapacity) {
	    Object oldData[] = elementData;
	    int newCapacity = (oldCapacity * 3)/2 + 1;
    	    if (newCapacity < minCapacity)
		newCapacity = minCapacity;
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
	}
    }

 在创建ArrayList对象的时候,如果没有指定大小,默认ArrayList的size为10;在添加元素的时候,如果当前空间不足,会按照上面的ensureCapacity的方法来扩容,扩容后的大小是原先的1.5倍。因此elementData数组很可能没有放满,会有很多无效的null元素,默认的序列化会把无效的null元素也序列化,影响效率。

 

 

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

	return (E) elementData[index];
    }

    public boolean add(E e) {
	ensureCapacity(size + 1);  // Increments modCount!!
	elementData[size++] = e;
	return true;
    }

    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; // Let gc do its work

	return oldValue;
    }

 上面是ArrayList的常见的方法,可以看到,实质上就是做些数组的操作。

 

 

下面先来看下Vector的源码:

 

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

 Vector的声明跟ArrayList一样,也是实现了List<E>, RandomAccess, Cloneable, java.io.Serializable这几个接口。

 

 

private void ensureCapacityHelper(int minCapacity) {
	int oldCapacity = elementData.length;
	if (minCapacity > oldCapacity) {
	    Object[] oldData = elementData;
	    int newCapacity = (capacityIncrement > 0) ?
		(oldCapacity + capacityIncrement) : (oldCapacity * 2);
    	    if (newCapacity < minCapacity) {
		newCapacity = minCapacity;
	    }
            elementData = Arrays.copyOf(elementData, newCapacity);
	}
    }

 上面是Vector的扩容方法,当空间不足时,会分配 size * 2的空间。

 

 

public synchronized E elementAt(int index) {
	if (index >= elementCount) {
	    throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
	}

        return (E)elementData[index];
    }

 public synchronized void addElement(E obj) {
	modCount++;
	ensureCapacityHelper(elementCount + 1);
	elementData[elementCount++] = obj;
    }

public synchronized void removeElementAt(int index) {
	modCount++;
	if (index >= elementCount) {
	    throw new ArrayIndexOutOfBoundsException(index + " >= " +
						     elementCount);
	}
	else if (index < 0) {
	    throw new ArrayIndexOutOfBoundsException(index);
	}
	int j = elementCount - index - 1;
	if (j > 0) {
	    System.arraycopy(elementData, index + 1, elementData, index, j);
	}
	elementCount--;
	elementData[elementCount] = null; /* to let gc do its work */
    }

 上面是Vector的常见的方法,跟ArrayList的主要区别是在方法上加了synchronized关键字。

 

 

 

0
1
分享到:
评论
3 楼 pi88dian88 2014-01-22  
string2020 写道
楼主能不能谈谈 Hashtable,ConcurrentHashMap
这两个的区别,这两个都是hash表,都是同步的。

有什么区别


, 谢谢来踩,也只是简单的介绍下
http://pi88dian88.iteye.com/blog/2008160
2 楼 kidneyball 2014-01-09  
string2020 写道
楼主能不能谈谈 Hashtable,ConcurrentHashMap
这两个的区别,这两个都是hash表,都是同步的。

有什么区别


Hashtable的任何操作都会把整个表锁住,是阻塞的。好处是总能获取最实时的更新,比如说线程A调用putAll写入大量数据,期间线程B调用get,线程B就会被阻塞,直到线程A完成putAll,因此线程B肯定能获取到线程A写入的完整数据。坏处是所有调用都要排队,效率较低。

ConcurrentHashMap是设计为非阻塞的。在更新时会局部锁住某部分数据,但不会把整个表都锁住。同步读取操作则是完全非阻塞的。好处是在保证合理的同步前提下,效率很高。坏处是严格来说读取操作不能保证反映最近的更新。例如线程A调用putAll写入大量数据,期间线程B调用get,则只能get到目前为止已经顺利插入的部分数据。此外,使用默认构造器创建的ConcurrentHashMap比较占内存,如果程序需要创建巨量ConcurrentHashMap,应该在构造时指定concurrencyLevel (详情参考 http://ria101.wordpress.com/2011/12/12/concurrenthashmap-avoid-a-common-misuse/ )。
1 楼 string2020 2014-01-08  
楼主能不能谈谈 Hashtable,ConcurrentHashMap
这两个的区别,这两个都是hash表,都是同步的。

有什么区别

相关推荐

    Java中的ArrayList的底层源码解读、LinkedList、Vector的区别介绍

    适用人群:JavaSE初学者,对源码感兴趣的,想要深度了解ArrayList底层实现、数据结构、add方法、Remove方法、以及自动扩容机制的同学,并且对ArrayList已经有过使用,想要学习它与LinkedList,Vector等的区别,该...

    ArrayList源码.zip

    ArrayList是Java编程语言中最常用的集合...总之,这个“ArrayList源码.zip”文件是Java程序员学习和优化代码的宝贵资源,它揭示了ArrayList内部的工作机制,帮助我们提升编程技巧,更好地理解和利用这个强大的集合类。

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

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

    java源码整理包-集合

    在这个“java源码整理包-集合”中,包含了多种核心的集合类的源代码,如`List`、`Map`、`ArrayList`、`HashMap`、`HashSet`、`Hashtable`、`TreeMap`、`TreeSet`和`Vector`。这些源码对于深入理解Java集合的工作原理...

    java模仿千千静听播放器源码

    总结来说,这个"java模仿千千静听播放器源码"项目涵盖了Java Swing图形界面设计、Java Sound音频处理、数据结构与算法(如歌曲列表的管理)、多线程编程、资源管理(皮肤切换)以及面向对象设计等多个重要知识点。...

    Java常用类源码

    以上只是Java常用类的一部分,实际上还有很多其他重要的类,如`ArrayList`的同胞`Vector`,线程安全的`ConcurrentHashMap`,网络编程中的`Socket`和`ServerSocket`等。通过深入学习这些类的源码,不仅可以提高编程...

    最全的Java面试题、读书笔记、面试经验

    java面试 【作品名称】:最全的Java面试题、读书笔记、面试经验 【适用人群】:适用于希望学习不同... * [Vector源码剖析](Part2/JavaSE/Vector源码剖析.md) * [HashMap源码剖析](Part2/JavaSE/HashMap源码剖析.md)

    java-data-struct.rar_数据结构 java_数据结构源码

    "java-data-struct.rar_数据结构 java_数据结构源码"这个压缩包文件包含了用Java实现的数据结构的相关代码,对于学习和理解数据结构的实现具有很高的参考价值。 1. **链表(LinkedList)**:链表是一种线性数据结构...

    java8源码-JavaRobot:Java学习笔记,JavaLearningNote

    学习笔记(持续更新中) 所有文章均同步发布到微信公众号【JavaRobot】,关注微信公众号,及时得到文章推送,谢谢支持。 说明:如无特别说明,所有代码都基于JDK8 JavaSE(Java基础) Java Core 关键字 synchronized...

    javaarraylist源码-Data-Structures-Algorithms:使用Java编程语言的数据结构和算法源代码(包括Stac

    在这个名为"javaarraylist源码-Data-Structures-Algorithms"的项目中,开发者分享了关于ArrayList和其他数据结构与算法的源代码实现,如Stack、LinkedList、Queue以及Binary Tree。 ArrayList的内部实现基于数组,...

    java并发编程艺术源码

    通过对《Java并发编程艺术》源码的深入学习,你可以掌握上述知识点,并能够运用到实际项目中,编写出更加稳定和高效的并发程序。书中的例子和源码将有助于你理解和实践这些理论,从而提升你的并发编程能力。

    awt学生信息管理源码分享源码学习a

    4. 学习与调试:逐步阅读源码,理解每个类和方法的功能,通过调试工具观察程序运行过程,加深理解。 总之,这个AWT学生信息管理系统源码是一个很好的学习资源,它涵盖了Java GUI编程的基本概念和技术,同时也涉及到...

    Java数据结构学习资料源码.zip

    这份"Java数据结构学习资料源码.zip"包含了一系列与数据结构相关的学习资源,特别针对Java初学者,提供详细的代码案例,帮助他们从实践中理解这些基础概念。 首先,让我们探讨一下数据结构的基本概念。数据结构是...

    java并发源码分析之实战编程

    总之,"java并发源码分析之实战编程"涵盖了许多关键知识点,从基本的线程操作到复杂的并发设计模式,都需要开发者深入学习和实践。通过研究源码,我们可以更深入地理解这些机制的工作原理,从而在实际开发中做出更优...

    java数据结构源码

    3. **栈**(Stack):栈是一种后进先出(LIFO)的数据结构,Java的`java.util.Stack`类是基于`Vector`实现的,支持常见的栈操作如`push`、`pop`、`peek`等。 4. **队列**(Queue):队列是一种先进先出(FIFO)的...

    JAVA源码阅读的真实体会.pdf

    阅读这些源码可以帮助理解基础操作的实现,比如ArrayList和Vector的区别,通过阅读源码可以加深记忆。 进一步,可以研究core包中的String和StringBuffer,如果对Java IO有了解,可以尝试阅读FileReader等相关类。...

    Java手机游戏海底探险源文件

    在这个项目中,开发者可能使用了Java的Canvas类来绘制游戏画面,用ArrayList或Vector来管理游戏对象,以及利用SerialObject或 RMS(Record Management System)进行数据存储。此外,游戏可能还包含网络功能,如排行...

    Java课程设计--java swing学生信息管理系统(源码+数据库+文档) .zip

    这个系统提供了完整的源码、数据库以及相关的文档,对于学习Java GUI编程和数据库操作的学员来说,是一个非常实用的学习资源。 1. **Java Swing**: Java Swing是Java AWT(Abstract Window Toolkit)库的扩展,提供...

    使用Vector实现简单线程池

    尽管`Vector`在Java集合框架中已经被`ArrayList`和`LinkedList`等更高效的类取代,但它的线程安全性使其在多线程编程的示例中仍然有用。不过,实际生产环境中的线程池实现往往会选择更高效的数据结构,例如`...

Global site tag (gtag.js) - Google Analytics