讨论:如何高效使用List

 大家都知道Java list 的实现类有两个,分别是:ArrayList、LinkedList。实际工作中,使用最多的是ArrayList。ArrayList 的底次实现是数据,LinkedList的层次是链表。书上告诉我们:当需要在List中间插入数据时,应该使用LinkedList,ArrayList 有高效的访问效率。真的是这样的吗?看如下的代码:

List<Integer> arrays = new ArrayList<Integer>();
for (int i = 0; i < 10000; i++) {
	arrays.add(i);
}

  向一个List中插入10000个数据,应该使用ArrayList?我们来简单的分析一下ArrayList的代码:

 

    public ArrayList(int initialCapacity) {
	super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
	this.elementData = new Object[initialCapacity];
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
	this(10);
    }

  可以看出:ArrayList 存储数组的初始长度是 10 。那么,当数组满了时,ArrayList是怎么样做的呢?继续看代码:

 

 

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

 

    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中添加一个数据时,调用 ensureCapacity 方法,判断数组的空间是否能满足存储当前数据的条件,如不能,使用Arrays.copyOf(oldArray,newLength) 把数组中的旧数据copy到一个新的、更长的数组中。在copy过程中,是这么做的:首先CPU寻址:找到一个连续的、空白的、满足指定长度的空闲内存块,找到后,进行搬数据操作。这个过程会随着数据越来越多,数组的长度越来越大,效率会急剧下降。因此,当我们使用List来存储“大数据”时,首选LinkedList。好处是:LinkedList 是使用链表来存储数据,向LinkedList中插入数据时,不会出现寻址和copy数据的操作,更正确的说,会更快的找到满足存储条件的空闲块。基于上述理由:代码修改为:

List<Integer> arrays = new LinkedList<Integer>();
for (int i = 0; i < 1000; i++) {
	arrays.add(i);
}

 LinkedList 也存在不足之处:如下代码:

for (Integer val : arrays) {
	System.out.println(val);
}

 循环遍历List。如果List是LinkedList实现的,每遍历一个元素,都要寻找下个数据的地址,因为元素并不是存储在连续的内存块中。这时的寻址也会很“消费时间”。优化方法:把生成后的LinkedList再放入一个ArrayList中,生成一个ArrayList 对象,ArrayList 的存储在内存块中是连续存放的,在遍历时,不会因寻址“浪费时间”了。优化后的代码如下:

List<Integer> arrays = new LinkedList<Integer>();
for (int i = 0; i < 1000; i++) {
	arrays.add(i);
}
arrays = new ArrayList<Integer>(arrays);
for (Integer val : arrays) {
	System.out.println(val);
}

  上面讲到的方法,并没有进行严格的测试,肯定会有不足之处。欢迎大家批评!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值