三大类list的效率比较---1.

来源:互联网 发布:淘宝会员怎么取消 编辑:程序博客网 时间:2024/04/28 13:40

src: http://www.cnblogs.com/zealotrouge/



   先说下我所认为的程序员素养吧,我认为应包括以下几个方面呢:1,扎实的功底——扎实掌握操作系统,数据结构等大学基本课程,鼓吹基础无用论的,必定是个三流程序

员。2,学习心态——对你所调用的,一定要有好奇心,尽可能花时间去了解API背后的东西,去了解系统框架是如何运作;对新的领域,一定要有好奇心,多尝试多学习,他山之石,可以攻玉。3,善于自学、总结、发问——工作后没有人去手把手教你,只要自己刻苦专研,并总结成博客或者笔记之类的成果,才又提高;在遇到自己能力范围内解决不了的问题,要善于向牛人请求点播,而一针见血的问题往往也会收获一针见血的回答。

  举一个简单的例子来讨论素养1,需求如下:已经完成排序的1万条数据,现在需要取前5000条作为最终数据,考虑到数据量较大,如果是新建列表,遍历旧列表的5000条并重新建立引用,有(引用类型所占字节 * 5000)字节的空间上的浪费,而且这种方式显得比较笨拙。

  所以,略加思索后写出了以下代码:

List<Item> rankItems = new ArrayList<Item>();// 生成数据+排序...while (rankItems.size() > 5000) {    rankItems.remove(rankItems.size() - 1);}

  简单分析,对于ArrayList大家都不陌生,是以数组方式实现的链表,remove(index)方法实质上调用的是System.arraycopy()方法,源码如下:

    /**     * Removes the object at the specified location from this list.     *     * @param index     *            the index of the object to remove.     * @return the removed object.     * @throws IndexOutOfBoundsException     *             when {@code location < 0 || >= size()}     */    @Override public E remove(int index) {        Object[] a = array;        int s = size;        if (index >= s) {            throwIndexOutOfBoundsException(index, s);        }        @SuppressWarnings("unchecked") E result = (E) a[index];        System.arraycopy(a, index + 1, a, index, --s - index);        a[s] = null;  // Prevent memory leak        size = s;        modCount++;        return result;    }

  System.arraycopy()是native方法,调用的应该是C语言中的memcpy(),虽然copy的source地址和dest地址都是相同的,无需分配新内存,但是要经过5000次的内存IO读写才能删除ArrayList中的数据。究其原因是因为ArrayList的数组实现方式,不利于在指定位置做添加/删除操作,所以思考后有了以下代码:

List<Item> rankItems = new LinkedList<Item>();// 生成数据+排序...while (rankItems.size() > 5000) {    rankItems.remove(rankItems.size() - 1);}

  再分析LinkedList的删除效率,是否比ArrayList高了呢?LinkedList的remove(index)方法实现如下:

/**     * Removes the object at the specified location from this {@code LinkedList}.     *     * @param location     *            the index of the object to remove     * @return the removed object     * @throws IndexOutOfBoundsException     *             if {@code location < 0 || >= size()}     */    @Override    public E remove(int location) {        if (0 <= location && location < size) {            Link<E> link = voidLink;            if (location < (size / 2)) {                for (int i = 0; i <= location; i++) {                    link = link.next;                }            } else {                for (int i = size; i > location; i--) {                    link = link.previous;                }            }            Link<E> previous = link.previous;            Link<E> next = link.next;            previous.next = next;            next.previous = previous;            size--;            modCount++;            return link.data;        }        throw new IndexOutOfBoundsException();    }

  LinkedList的删除操作很简单,只需要修改指定index对象其前后对象的引用即可,但是在指针移动到指定index之前,需要移动1/2个列表长度,效率并非最高,能否将移动的操作也简化掉呢?既然是已排好序的列表,每次删除都删除列表末尾的对象,那我们可以使用LinkedList提供的removeLast()方法,代码如下:

List<Item> rankItems = new LinkedList<Item>();// 生成数据+排序...while (rankItems.size() > 5000) {    rankItems.removeLast();}

  分析removeLast()的效率,LinkedList的removeLast()方法实现如下:

/**     * Removes the last object from this {@code LinkedList}.     *     * @return the removed object.     * @throws NoSuchElementException     *             if this {@code LinkedList} is empty.     */    public E removeLast() {        Link<E> last = voidLink.previous;        if (last != voidLink) {            Link<E> previous = last.previous;            voidLink.previous = previous;            previous.next = voidLink;            size--;            modCount++;            return last.data;        }        throw new NoSuchElementException();    }

  LinkedList的removeLast()方法没有移动指针的操作,只需要借助于列表尾的voidLink,即可完成对列表尾部对象的删除,效率上较高。

0 0
原创粉丝点击