`
akunamotata
  • 浏览: 378749 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多

 

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

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

 

分享到:
评论
25 楼 mbjian 2011-08-08  
akunamotata 写道
其实觉得可以直接使用java.util.ArrayList,为什么要实现一个静态内部类?也是出于性能的考虑?

24 楼 yuxiaojicai 2011-01-26  
次“ArrayList”非彼“ArrayList”,一句话足够了
23 楼 yangyi 2011-01-25  
落依然 写道
aoliwen521 写道
Turbo 写道
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量

我觉得不是基于性能的考量,留意它的名字,Arrays as List,就是array的本质没有变,只是以List的形式出现,方便使用而已.

同意,觉得这个才是正解。
底层仍然是一个数组,保持数组能拥有的所有操作。
比如修改某一个元素,或者遍历。
但是不能够改变长度。
只是以List形态出现,为了某些仅对List读操作的方法可以顺利的执行。



为什么要转为List?接口适配
怎么转List?简单高效,不能进行Array Copy
所以:
第一,1是根本目的,没人否认
第二,2是实现方法,快在构造上,不在使用上
第三,本人之前讨论的是为什么没有返回java.util.ArrayList而重新设计了一个List,其他一切讨论都与此无关,典型的无关说法有:
a) 读的速度快,写也差不多 —— 俺说的是构造是没有Array Copy是基于性能考虑
b)名字叫asList,所以返回一个List,底层仍然是数组 ——参考第一点
引用
我觉得不是基于性能的考量

这句话要有上下文才能理解,就是什么不是基于性能的考量,asList这个方法的存在本身当然不是基于性能的考量,那是基于需求的考量
22 楼 落依然 2011-01-25  
aoliwen521 写道
Turbo 写道
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量

我觉得不是基于性能的考量,留意它的名字,Arrays as List,就是array的本质没有变,只是以List的形式出现,方便使用而已.

同意,觉得这个才是正解。
底层仍然是一个数组,保持数组能拥有的所有操作。
比如修改某一个元素,或者遍历。
但是不能够改变长度。
只是以List形态出现,为了某些仅对List读操作的方法可以顺利的执行。

21 楼 snowflate_summer 2011-01-25  
akunamotata 写道
AllenZhang 写道
asList返回的是内部的ArrayList.其和java.util.ArrayList不同。最大的区别就是没有add方法,只能扔exception.
内部ArrayList类,性能并不是最大考虑的,而是在设计的意义上,数组应该是固定大小的。



我赞同,如果光是读的话,性能是一样的。



我也同意这个观点
20 楼 sydra 2011-01-25  
别想了,看看api就知道了
public static <T> List<T> asList(T... a)返回一个受指定数组支持的固定大小的列表。
既然是固定大小了,自然不能add,那么也自然不能用java.util.ArrayList类的实例.
看看这个静态ArrayList就知道了,它是一个不可变对象,既高效又安全.
19 楼 aoliwen521 2011-01-25  
Turbo 写道
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量

我觉得不是基于性能的考量,留意它的名字,Arrays as List,就是array的本质没有变,只是以List的形式出现,方便使用而已.

同意,觉得这个才是正解。
底层仍然是一个数组,保持数组能拥有的所有操作。
比如修改某一个元素,或者遍历。
但是不能够改变长度。
只是以List形态出现,为了某些仅对List读操作的方法可以顺利的执行。
18 楼 Turbo 2011-01-25  
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量

我觉得不是基于性能的考量,留意它的名字,Arrays as List,就是array的本质没有变,只是以List的形式出现,方便使用而已.
17 楼 akunamotata 2011-01-25  
skyuck 写道
书中说的没错呀,底层确实是一个数组
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;
}


数组是没错,但是java.util.ArrayList提供了add方法来改变这个数组的大小,你可以看下它的源码。
这个静态内部类不是不可以实现这个add方法,而是在设计的意义上,数组应该是固定大小的。
16 楼 skyuck 2011-01-25  
书中说的没错呀,底层确实是一个数组
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;
}
15 楼 skyuck 2011-01-25  
这点恰好昨天我也看了,我要学习楼主这种精神
14 楼 akunamotata 2011-01-24  
AllenZhang 写道
asList返回的是内部的ArrayList.其和java.util.ArrayList不同。最大的区别就是没有add方法,只能扔exception.
内部ArrayList类,性能并不是最大考虑的,而是在设计的意义上,数组应该是固定大小的。



我赞同,如果光是读的话,性能是一样的。
13 楼 mercyblitz 2011-01-24  
HelloJimmy 写道
Java Collection Framework中只保证了基本实现中会实现接口中的所有方法,其他实现类中不必全部实现,如果不实现的话,要抛出异常;

对于List接口基本实现就是util包中的ArrayList和LinkedList了;

Arrays.asList返回一个静态数组的原因,我同意yangyi的,是为了性能;

如果要resize的话,再用util包里的ArrayList来包装下OK了;



如果是Fixed size,java.util.ArrayList(注意构造参数)和Arrays.asList的读速度不是一样吗?

那里提高的性能?
12 楼 HelloJimmy 2011-01-24  
Java Collection Framework中只保证了基本实现中会实现接口中的所有方法,其他实现类中不必全部实现,如果不实现的话,要抛出异常;

对于List接口基本实现就是util包中的ArrayList和LinkedList了;

Arrays.asList返回一个静态数组的原因,我同意yangyi的,是为了性能;

如果要resize的话,再用util包里的ArrayList来包装下OK了;
11 楼 captmjc 2011-01-24  
akunamotata 写道
其实觉得可以直接使用java.util.ArrayList,为什么要实现一个静态内部类?也是出于性能的考虑?


保证这个List永远是这个Array的实时数据,并且,这个List永远是只读的
10 楼 AllenZhang 2011-01-24  
asList返回的是内部的ArrayList.其和java.util.ArrayList不同。最大的区别就是没有add方法,只能扔exception.
内部ArrayList类,性能并不是最大考虑的,而是在设计的意义上,数组应该是固定大小的。
9 楼 mercyblitz 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或着同步的。很多语义可以保证。
8 楼 yangyi 2011-01-24  
mercyblitz 写道
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量



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

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

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

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

这个理解有点问题,数组不是线程安全的,除非:
int[] a = {};
syn{
  a[i] = xx;
}
性能上,这个的效率确实是比ArrayList高的,对比一下源码就清楚了
7 楼 piao_bo_yi 2011-01-24  
Arrays这个类明显想表示数组的概念。数组当然是不可以扩充了。ArrayList表示线性表的概念。概念不同。
6 楼 mercyblitz 2011-01-24  
yangyi 写道
没有做Array Copy动作,应该是基于性能的考量



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

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

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

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

相关推荐

    Java中Arrays.asList()方法详解及实例

    Java中Arrays.asList()方法详解及实例 Arrays.asList()方法是Java中一个常用的方法,它将数组转换为列表。该方法的签名为`public static &lt;T&gt; List&lt;T&gt; asList(T... a)`,它可以接受变长参数,通常情况下是一个数组...

    Arrays.asList方法总结

    `Arrays.asList`方法是Java中一个非常实用的工具,它允许我们将数组转换为`List`对象,以便在处理数组时可以利用`List`接口提供的便利。然而,这个方法有一些特殊的特性和限制,需要我们理解清楚才能正确使用。下面...

    Java Arrays.asList使用方法解析

    "Java Arrays.asList使用方法解析" ...Java Arrays.asList使用方法解析是一个非常重要的知识点,需要我们牢记Arrays.asList方法返回的ArrayList对象的行为与我们通常使用的List集合不同,以避免在编程中出现错误。

    Java用Arrays.asList初始化ArrayList实例方法

    Java中使用Arrays.asList初始化ArrayList实例方法 在 Java 中,使用 Arrays.asList 方法可以快速创建一个 List 集合,但是需要注意的是,这个方法返回的 ArrayList 并不是 java.util.ArrayList 对象,而是一个内部...

    浅谈Arrays.asList() 和ArrayList类型区别

    在Java编程中,Arrays.asList()方法和ArrayList是两种不同的方式来处理列表数据,它们之间存在显著的区别。这篇文章将深入探讨这两个概念以及它们在实际使用中的差异。 首先,Arrays.asList()是一个Java内置方法,...

    java 源码分析Arrays.asList方法详解

    Java中的`Arrays.asList()`方法是Java集合框架的一部分,它允许我们将数组或变长参数转换为一个固定大小的`List`对象。这个方法在处理数组与集合之间的转换时非常有用,尤其是当你需要使用集合API操作数组时。下面...

    浅谈Arrays.asList()方法的使用

    在Java编程中,`Arrays.asList()`方法是一个非常实用的工具,它允许我们将数组转换成一个`List`对象。这个方法在处理数组与集合之间的转换时,提供了很大的便利。下面我们将深入探讨`Arrays.asList()`方法的使用细节...

    在项目中用了Arrays.asList、ArrayList的subList,被公开批评.html

    Arrays.asList、ArrayList的subList坑

    flyhero#MarkNote#用过Arrays.asList的注意了1

    而一开始asList()的设计时用于打印数组而设计的,但jdk1.5开始,有了另一个比较更方便的打印函数Arrays.toString(),于是打印不再使用as

    Thinking in Java 3th Edition.zip

    《Thinking in Java》是Bruce Eckel的经典编程教材,第三版主要涵盖了Java编程语言的核心概念和技术。这本书深入浅出地介绍了面向对象编程的思想,是初学者和有经验的程序员理解Java的宝贵资源。以下是对该书内容的...

    JAVA基于Arrays.sort()实现数组升序和降序

    在 Java 中,排序数组是非常常见的操作之一,而 Java 提供了多种方式来实现数组的排序,其中一种常用的方法是使用 Arrays.sort() 方法。今天,我们将详细介绍如何使用 Arrays.sort() 方法来实现数组的升序和降序排序...

    System.arraycopy和Arrays.copyOf

    `System.arraycopy` 和 `Arrays.copyOf` 都是Java中用于复制数组的方法,但它们在使用和处理异常情况上有所不同。这两个方法在处理数组复制时,提供了便利和效率,但各有其适用场景。 `System.arraycopy` 是一个...

    list使用过程中遇到的坑

    当我们在实际业务开发过程中,难免会遇到数组转List的操作,通常我们所选择的就是上面的Arrays.asList进行操作,但是,对的但是来了,我们在使用的时候会发现基本数据类型的参数转化的结果会和我们想要的结果完全不...

    java随机生成字符串(字符随机生成类 生成随机字符组合).docx

    temp.addAll(Arrays.asList(lowercase)); } else if (type == TYPE.CAPITAL) { temp.addAll(Arrays.asList(capital)); } else if (type == TYPE.NUMBER) { temp.addAll(Arrays.asList(number)); } else if ...

    JAVA高级技术.pdf

    在Java中,我们可以将数组转换为List对象,利用`Arrays.asList()`方法即可实现。例如: ```java String[] animals = {"Tiger", "Lion", "Cat", "Dog", "Deer", "Chicken", "Sheep", "Horse", "Rabbit", "Snake"};...

    Java Arrays.sort和Collections.sort排序实现原理解析

    在本例中,由于使用了`Arrays.asList()`创建列表,因此实际的子类是`ArrayList`。`ArrayList`的`sort()`方法最终会调用`Arrays.sort()`。 `Arrays.sort()`的实现相当复杂,它采用了混合排序算法——TimSort。...

    你清楚Arrays.binarySearch()方法的返回值吗?

    `Arrays.binarySearch()`方法允许我们在有序数组中查找指定元素,并返回该元素的索引。如果数组中不存在该元素,则会返回一个负数,这个负数的绝对值是插入该元素位置的前一个位置。 首先,让我们详细了解一下`...

    深入理解java中Arrays.sort()的用法

    "深入理解Java中Arrays.sort()的用法" 在Java中,Arrays.sort()是一个非常重要的方法,它可以对数组进行排序。该方法是Arrays类的静态方法,在需要对数组进行排序时,非常的好用。但是sort()的参数有好几种,基本上...

    Thinking in Java 4th Edition + Annotated Solution Guide (代码)英文文字版 带书签 有答案

    《Thinking in Java》是Bruce Eckel的经典之作,第四版涵盖了Java编程语言的广泛主题,适合初学者和有经验的程序员。这本书深入浅出地讲解了Java的核心概念和技术,旨在帮助读者建立坚实的编程基础,并理解面向对象...

Global site tag (gtag.js) - Google Analytics