精华帖 (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; } 不知道我解释的对么?大家可以讨论一下这个问题。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-01-23
我想是因为翻译的问题,原文中有fixed-size array一词,而翻译过来时只是提到数组而已。
|
|
返回顶楼 | |
发表时间:2011-01-23
没有做Array Copy动作,应该是基于性能的考量
|
|
返回顶楼 | |
发表时间:2011-01-23
最后修改:2011-01-23
其实觉得可以直接使用java.util.ArrayList,为什么要实现一个静态内部类?也是出于性能的考虑?
|
|
返回顶楼 | |
发表时间:2011-01-24
akunamotata 写道 其实觉得可以直接使用java.util.ArrayList,为什么要实现一个静态内部类?也是出于性能的考虑?
因为如果是用数组作为方法参数,那么set(int index, E element)这个方法的会直接修改掉关联的那个数组。这个如果是add了,那加到哪里呢? |
|
返回顶楼 | |
发表时间:2011-01-24
yangyi 写道 没有做Array Copy动作,应该是基于性能的考量
因为这样做的目的主要是为了像List一样操作那个数组,提供的一个包装,而不是新拷贝的一个数组。 |
|
返回顶楼 | |
发表时间:2011-01-24
yangyi 写道 没有做Array Copy动作,应该是基于性能的考量
不是性能的问题,相对于java.util.ArrayList而言,内部ArrayList的实现更加消耗性能,抛出异常。 两个方面:线程安全和代码安全。 线程安全,只提List安全,不是说里面的元素安全。 代码安全,不希望Client调用时,修改内部构造。实际上,还是不太安全,相对于Google的Collection。 |
|
返回顶楼 | |
发表时间:2011-01-24
Arrays这个类明显想表示数组的概念。数组当然是不可以扩充了。ArrayList表示线性表的概念。概念不同。
|
|
返回顶楼 | |
发表时间:2011-01-24
mercyblitz 写道 yangyi 写道 没有做Array Copy动作,应该是基于性能的考量
不是性能的问题,相对于java.util.ArrayList而言,内部ArrayList的实现更加消耗性能,抛出异常。 两个方面:线程安全和代码安全。 线程安全,只提List安全,不是说里面的元素安全。 代码安全,不希望Client调用时,修改内部构造。实际上,还是不太安全,相对于Google的Collection。 这个理解有点问题,数组不是线程安全的,除非: int[] a = {}; syn{ a[i] = xx; } 性能上,这个的效率确实是比ArrayList高的,对比一下源码就清楚了 |
|
返回顶楼 | |
发表时间: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或着同步的。很多语义可以保证。 |
|
返回顶楼 | |