Think in Java -- Holding Your Object(ArrayList 部分)

  今天在看Holding Your Object这一样,这一章初步讲解Java中的容器类。在这里,我也按照书上讲的顺序介绍容器,部分是书上讲的,自己觉得比较重要的;部分是自己的体会。

  1. ArrayList
  2. Arrays.asList()
  • ArrayList是我们在Java中使用的比较频繁的一个类(起码是我使用比较频繁的一个微笑。)当我们在创建这个类的时候,我们可以制定里面到底是存放什么类型的数据,这样能给我们编程带来很多的方面。因为如果放入的类型不是指定的类型或者其子类的话,在编译的时候就会出现错误。这些其实是泛型的内容。
  • ArrayList是一个容器,所以能够动态的扩展。在这里讲讲ArrayList的初始大小,以及如何扩展的。

初始大小,ArrayList中有三个构造函数:
public ArrayList(int initialCapacity) {
		super();
		if (initialCapacity < 0)
			throw new IllegalArgumentException("Illegal Capacity: "
					+ initialCapacity);
		this.elementData = new Object[initialCapacity];
	}
上面这个构造函数,是在申明的时候定义了初始的大小。
public ArrayList() {
		this(10);
	}
当我们使用一个没有参数的构造函数,初始的大小是10.
public ArrayList(Collection<? extends E> c) {
		elementData = c.toArray();
		size = elementData.length;
		// c.toArray might (incorrectly) not return Object[] (see 6260652)
		if (elementData.getClass() != Object[].class)
			elementData = Arrays.copyOf(elementData, size, Object[].class);
	}
另外,也可以直接使用Collection来初始化这个ArrayList,这样ArrayList的初始大小就是这个Collection的大小。
如何扩展的呢?
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执行add或者addAll操做前要先执行的一个函数,minCapacity是增加后,最小需要的容量。如果当前容量足够的话,就不增加,如果不够的话,就会按照oladCapacity * 23 / 2 + 1的方式来扩充容量。如果扩充之后还是不够的话,就直接按照minCapacity。在扩充的过程中,我们也发现,会使用较大的内存,这个是Arrays.copyOf的实现了。

  • ArrayList到array的转化
在ArraList中,有一个toArray的方法,可以把ArrayList直接转化成array。toArray()这个方法有重载函数。
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }
toArray(),就直接返回一个Object的数组。
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // Make a new array of a's runtime type, but my contents:
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
	System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > siz
            a[size] = null;
        return a;
    }
toArray(T[] a)会返回一个对应类型的数组。但是在这里,我们需要注意的是,当a中的容量足以存放这个ArrayList的时候,就直接放到了a数组里,所以会修改a数组的值。但是如果不够的话,就直接copy成一个数组,这样a数组是不会变化的。

  • ArrayList中是不能进行向上转化的
先上例子,然后慢慢解释。
class A{
	}
	
class B extends A{
}


public class ArrayListTest {
	public static void main(String args[]) {
		List<A> arraya = new ArrayList<A>();
		//List<A> arrayb = new ArrayList<B>();
		//exception Type mismatch: cannot convert from ArrayList<B> to List<A>
		
		A[] a;
		B[] b = new B[0];
		a = b;
	}
}


在上面的代码中,我们看到,虽然B是A的子类,但是ArrayList<B>不能转化到ArrayList<A>,但是数组是可以的。在这个基础上,就能比较好的理解书中的一个例子了。
class Snow {
}

class Powder extends Snow {
}

class Light extends Powder {
}

class Heavy extends Powder {
}

class Crusty extends Snow {
}

class Slush extends Snow {
}

public class AsListInference {
	public static void main(String[] args) {

		List<Snow> snow1 = Arrays.asList(new Crusty(), new Slush(),
				new Powder());

		// Won’t compile:
		// List<Snow> snow2 = Arrays.asList(
		// new Light(), new Heavy());
		// Compiler says:
		// found : java.util.List<Powder>
		// required: java.util.List<Snow>

		List<Snow> snow2 = Arrays.asList(new Light(), new Heavy(),
				new Powder(), new Crusty());

		List<Snow> snow3 = new ArrayList<Snow>();
		Collections.addAll(snow3, new Light(), new Heavy());
		// Give a hint using an
		// explicit type argument specification:
		List<Snow> snow4 = Arrays.<Snow> asList(new Light(), new Heavy());
	}
}


不能编译,是因为他们几个实例的最近的共同父类是Powder,所以会Arrays.asList只会创建一个ArrayList<Powder>的一个实例,所以会出现编译的错误。如果添加其他的几个实例,使他们的最近的共同父类是Snow,这样就可以了。这就是为什么我们添加了几个实例后,就不会编译错误的原因。

Arrays.asList
Arrays.asList的实现如下:
    public static <T> List<T> asList(T... a) {
	return new ArrayList<T>(a);
    }
当我看到上面代码的时候,我就认为就是使用a来构造一个新的ArrayList。但是下面的代码就会让你非常的疑惑。
public class AddingGroups {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);
		list.set(1, 99); // OK -- modify an element
		// list.add(21); // Runtime error because the
		// underlying array cannot be resized.
		// java.lang.UnsupportedOperationException
	}
}


上面代码注释的地方,竟然不能使用add的方法。所以自己看Arrays的实现,我们会发现,Arrays.toList中使用到的ArrayList其实是Arrays中自己的一个申明的类。
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;
}


这个内部的ArrayList类中,并没有实现add的方法。所以才会出现上面的exception。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值