论坛首页 Java企业应用论坛

《Thinking in Java》中Arrays.asList的解释错误

浏览 11579 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-01-23   最后修改:2011-01-26

 

List<Integer> list = Arrays.asList(16,17,18,19,20);
list.set(1, 99);
list.add(21);//运行时错误

 书中是这么解释的:其底层表示的是数组,因此不能调整尺寸。

 后来看了Arrays.asList的源码,发现了一些问题:

 

 

    public static <T> List<T> asList(T... a) {
	return new ArrayList<T>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
	implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
	private final E[] a;

	ArrayList(E[] array) {
            if (array==null)
                throw new NullPointerException();
	    a = array;
	}

	public int size() {
	    return a.length;
	}

	public Object[] toArray() {
	    return a.clone();
	}

	public <T> T[] toArray(T[] a) {
	    int size = size();
	    if (a.length < size)
		return Arrays.copyOf(this.a, size,
				     (Class<? extends T[]>) a.getClass());
	    System.arraycopy(this.a, 0, a, 0, size);
	    if (a.length > size)
		a[size] = null;
	    return a;
	}

	public E get(int index) {
	    return a[index];
	}

	public E set(int index, E element) {
	    E oldValue = a[index];
	    a[index] = element;
	    return oldValue;
	}

        public int indexOf(Object o) {
            if (o==null) {
                for (int i=0; i<a.length; i++)
                    if (a[i]==null)
                        return i;
            } else {
                for (int i=0; i<a.length; i++)
                    if (o.equals(a[i]))
                        return i;
            }
            return -1;
        }

        public boolean contains(Object o) {
            return indexOf(o) != -1;
        }
    }

 Arrays实现了一个静态内部类ArrayList,但是与java.util.ArrayList不同的是,并没有重写AbstractList的add方法。

然后再让我们看看AbstractList的add方法源码:

 

 

    /**
     * {@inheritDoc}
     *
     * <p>This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IndexOutOfBoundsException     {@inheritDoc}
     */
    public void add(int index, E element) {
	throw new UnsupportedOperationException();
    }

 AbstractList的add方法直接抛出了一个UnsupportedOperationException

因此,“底层表示的是数组,因此不能调整尺寸”这个理由十分牵强,同样java.util.ArrayList内部也是数组表示,但是实现了对象的添加。

这是ArrayList相关的源码:

 

 

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
	 ensureCapacity(size + 1);  // Increments modCount!!
	 elementData[size++] = e;
	 return true;
    }

 不知道我解释的对么?大家可以讨论一下这个问题。

 

   发表时间:2011-01-23  
我想是因为翻译的问题,原文中有fixed-size array一词,而翻译过来时只是提到数组而已。
0 请登录后投票
   发表时间:2011-01-23  
没有做Array Copy动作,应该是基于性能的考量
0 请登录后投票
   发表时间:2011-01-23   最后修改:2011-01-23
其实觉得可以直接使用java.util.ArrayList,为什么要实现一个静态内部类?也是出于性能的考虑?
0 请登录后投票
   发表时间:2011-01-24  
akunamotata 写道
其实觉得可以直接使用java.util.ArrayList,为什么要实现一个静态内部类?也是出于性能的考虑?

因为如果是用数组作为方法参数,那么set(int index, E element)这个方法的会直接修改掉关联的那个数组。这个如果是add了,那加到哪里呢?
0 请登录后投票
   发表时间:2011-01-24  
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量

因为这样做的目的主要是为了像List一样操作那个数组,提供的一个包装,而不是新拷贝的一个数组。
0 请登录后投票
   发表时间:2011-01-24  
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量



不是性能的问题,相对于java.util.ArrayList而言,内部ArrayList的实现更加消耗性能,抛出异常。

两个方面:线程安全和代码安全。

线程安全,只提List安全,不是说里面的元素安全。

代码安全,不希望Client调用时,修改内部构造。实际上,还是不太安全,相对于Google的Collection。
0 请登录后投票
   发表时间:2011-01-24  
Arrays这个类明显想表示数组的概念。数组当然是不可以扩充了。ArrayList表示线性表的概念。概念不同。
0 请登录后投票
   发表时间:2011-01-24  
mercyblitz 写道
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量



不是性能的问题,相对于java.util.ArrayList而言,内部ArrayList的实现更加消耗性能,抛出异常。

两个方面:线程安全和代码安全。

线程安全,只提List安全,不是说里面的元素安全。

代码安全,不希望Client调用时,修改内部构造。实际上,还是不太安全,相对于Google的Collection。

这个理解有点问题,数组不是线程安全的,除非:
int[] a = {};
syn{
  a[i] = xx;
}
性能上,这个的效率确实是比ArrayList高的,对比一下源码就清楚了
0 请登录后投票
   发表时间:2011-01-24  
yangyi 写道
mercyblitz 写道
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量



不是性能的问题,相对于java.util.ArrayList而言,内部ArrayList的实现更加消耗性能,抛出异常。

两个方面:线程安全和代码安全。

线程安全,只提List安全,不是说里面的元素安全。

代码安全,不希望Client调用时,修改内部构造。实际上,还是不太安全,相对于Google的Collection。

这个理解有点问题,数组不是线程安全的,除非:
int[] a = {};
syn{
  a[i] = xx;
}
性能上,这个的效率确实是比ArrayList高的,对比一下源码就清楚了


性能上,读方法是一样,写方法,这里的List是继承了AbstractList的方法,插入时有异常抛出。

我犯了有一点错误,这里不是线程安全,是因为它保留了一个set方法,修改数组内的结构,如果不算set的话,可以说是线程安全。

PS:线程安全不一定volatile或着同步的。很多语义可以保证。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics