guava之Lists常用示例及newArrayListWithExpectedSize()和newArrayListWithCapacity()详细对比

来源:互联网 发布:java 链表 编辑:程序博客网 时间:2024/05/17 03:37
谷歌提供了guava包里面有很多的工具类,现在先看Lists这个集合工具,对list集合操作做了些优化提升。

现提供如下使用实例。

package com.lxk.guavaTest;import com.google.common.collect.Lists;import java.util.List;/** * Created by lxk on 2016/11/7 */public class ListsTest {    public static void main(String[] args) {        testLists();    }    /**     * 测试 guava Lists     */    private static void testLists() {        List<String> list1 = Lists.newArrayList();        for (int i = 0; i < 10; i++) {            list1.add(i + "");        }        System.out.println("list1: " + list1);        List<String> list2 = Lists.newArrayList("1", "2", "3");        System.out.println("list2: " + list2);        List<String> list3 = Lists.newArrayList(new String[]{"22", "22"});        System.out.println("list3: " + list3);        List<String> list4 = Lists.newArrayList(list1);        System.out.println("list4: " + list4);        //下面的这个写法呢是在初始化list的时候,说明容器的扩容界限值        //使用条件:你确定你的容器会装多少个,不确定就用一般形式的        //说明:这个容器超过10个还是会自动扩容的。不用担心容量不够用。默认是分配一个容量为10的数组,不够将扩容        //执行数组数据迁移操作:新建新数组,复制就数组数据到新数组(包括开辟新空间,copy数据等等,耗时,耗性能)        //对下数字10的说明:若直接new一个list的话,默认大小是10的数组,下面的方式则是 5L + x + x/10 = 16L(x = 10),在17的时候扩容        //整个来说的优点有:节约内存,节约时间,节约性能。代码质量提高。        List<String> list = Lists.newArrayListWithExpectedSize(10);        //这个方法就是直接返回一个10的数组。        List<String> list_ = Lists.newArrayListWithCapacity(10);    }}


下面先是关于Lists.newArrayListWithExpectedSize(10)的源码简单分析

  @GwtCompatible(serializable = true)  public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {    return new ArrayList<E>(computeArrayListCapacity(estimatedSize));  }  static int computeArrayListCapacity(int arraySize) {    checkNonnegative(arraySize, "arraySize");    // TODO(kevinb): Figure out the right behavior, and document it    return Ints.saturatedCast(5L + arraySize + (arraySize / 10));  }  static int checkNonnegative(int value, String name) {    if (value < 0) {      throw new IllegalArgumentException(name + " cannot be negative but was: " + value);    }    return value;  }  public static int saturatedCast(long value) {    if (value > Integer.MAX_VALUE) {      return Integer.MAX_VALUE;    }    if (value < Integer.MIN_VALUE) {      return Integer.MIN_VALUE;    }    return (int) value;  }  public ArrayList(int initialCapacity) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+   initialCapacity);this.elementData = new Object[initialCapacity];}

然后是Lists.newArrayListWithCapacity(10)的源码简单分析

  @GwtCompatible(serializable = true)  public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {    checkNonnegative(initialArraySize, "initialArraySize"); // for GWT.    return new ArrayList<E>(initialArraySize);  }

然后看上面的主要是ArrayList,然后就看看ArrayList源码里面的add方法以及如何扩容的。

/** * list底层的用来保存数据的数组 */private transient Object[] elementData;/**     * Shared empty array instance used for empty instances.     */    private static final Object[] EMPTY_ELEMENTDATA = {};/**     * Default initial capacity.     */    private static final int DEFAULT_CAPACITY = 10;    public boolean add(E e) {        ensureCapacityInternal(size + 1);  // Increments modCount!! (Increments 翻译-- 增量; 增长( increment的名词复数 ); 增额; 定期的加薪;)        elementData[size++] = e;        return true;    }    private void ensureCapacityInternal(int minCapacity) { // Internal 翻译--  内部的; 国内的; 体内的; 内心的;   Capacity  翻译--  容量; 性能; 才能; 生产能力;        if (elementData == EMPTY_ELEMENTDATA) {            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);        }        ensureExplicitCapacity(minCapacity);    }    private void ensureExplicitCapacity(int minCapacity) { //Explicit  翻译-- 明确的,清楚的; 直言的; 详述的; 不隐瞒的;        modCount++;        // overflow-conscious code        if (minCapacity - elementData.length > 0) // 扩容条件,就是minCapacity = size + 1 大于当前数组的长度。就扩容。            grow(minCapacity);    }    private void grow(int minCapacity) {        // overflow-conscious code        int oldCapacity = elementData.length;        int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量相当于是原来容量的1.5倍(old + old>>1右移一位即除以2)        if (newCapacity - minCapacity < 0)            newCapacity = minCapacity;        if (newCapacity - MAX_ARRAY_SIZE > 0)            newCapacity = hugeCapacity(minCapacity);        // minCapacity is usually close to size, so this is a win:        elementData = Arrays.copyOf(elementData, newCapacity); // 复制旧数组数据到新数组    }

关于 ArrayList 的modCount属性,java源码里面写的注释很长一大串,不是一时半会可以看的明白的。我就做个记录,翻译一下。

    /**     * The number of times this list has been <i>structurally modified</i>.  这个list的结构已经被修改过的次数     * Structural modifications are those that change the size of the        结构修改是那些改变list的size属性,     * list, or otherwise perturb it in such a fashion that iterations in    或者其他方式如迭代进度可能会产生不正确的结果      * progress may yield incorrect results.     *     * <p>This field is used by the iterator and list iterator implementation  这个字段是由迭代器和列表迭代器实现的     * returned by the {@code iterator} and {@code listIterator} methods.      代码迭代器listIterator方法返回的代码     * If the value of this field changes unexpectedly, the iterator (or list  如果此字段的值意外更改,则迭代器(list迭代器)     * iterator) will throw a {@code ConcurrentModificationException} in       将在响应迭代器的next方法,remove方法,previous(),set(),add()等方法     * response to the {@code next}, {@code remove}, {@code previous},         抛出concurrentmodificationexception 异常     * {@code set} or {@code add} operations.  This provides                   这提供了     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in    快速失败的行为,而不是在面对迭代过程中,并发修改的非确定性行为     * the face of concurrent modification during iteration.     *     * <p><b>Use of this field by subclasses is optional.</b> If a subclass    子类们使用这个字段是可选的,如果一个子类     * wishes to provide fail-fast iterators (and list iterators), then it     希望提供快速失败的迭代器(lsit迭代器),那么 它     * merely has to increment this field in its {@code add(int, E)} and       仅仅需要增加这个字段在他的 add,remove,方法     * {@code remove(int)} methods (and any other methods that it overrides    (或者其他任何修改了list结构的方法)     * that result in structural modifications to the list).  A single call to  一个单一的调用     * {@code add(int, E)} or {@code remove(int)} must add no more than         add()或者remove()方法,必须增加不超过     * one to this field, or the iterators (and list iterators) will throw      1 的大小的值,给这个字段。否则,迭代器或者list迭代器将抛出     * bogus {@code ConcurrentModificationExceptions}.  If an implementation    ConcurrentModificationExceptions 异常   如果一个实现     * does not wish to provide fail-fast iterators, this field may be          不希望提供快速失败迭代器,这个字段可以忽视     * ignored.                                                   */





1 0