newArrayListWithExpectedSize()和newArrayListWithCapacity()详细对比

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.                                              
     */

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: lists.newarraylistwithcapacity是一个Java中的方法,用于创建一个指定容量的ArrayList列表。该方法可以接受一个整数参数,表示要创建的列表的容量大小。例如,以下代码将创建一个容量为10的ArrayList列表: List<String> list = new ArrayList<>(10); 该列表最初将具有10个空元素,但可以通过添加元素来动态地增加其大小。 ### 回答2: 在 Java 中,通过使用 ArrayList 类可以轻松地创建一个数组列表,可以随时添加或删除元素。当我们使用 ArrayList 创建一个新的数组列表时,会在内存中分配一段连续的空间来存储列表中的元素。通常情况下,这段空间的大小是动态调整的,以容纳所有的元素。 然而,在有些情况下,我们可能已经知道了数组列表中预计会有多少元素,这个时候我们就可以使用 ArrayList 的构造函数 newListArrayListWithCapacity(int initialCapacity) 来给列表设置一个固定的容量,从而在一开始就为列表分配足够的内存,避免了后续频繁的内存扩展和收缩带来的效率损失。 使用 newListArrayListWithCapacity() 函数创建一个具有固定容量的数组列表,需要传入一个整数类型的 initialCapacity 参数,该参数表示我们希望数组列表的容量大小。 需要注意的是,使用 newListArrayListWithCapacity() 构造函数创建的数组列表,其实际容量可能会大于或等于 initialCapacity,具体取决于 JVM 在内存分配时的规则和策略。因此,需要在使用数组列表时考虑其容量的大小,避免过分依赖固定容量而导致不必要的内存浪费。 除了 ArrayList,其他类似的容器类,如 HashSet 和 HashMap,也提供了类似的构造函数,用于指定容器的大小,以优化内存使用和效率。 ### 回答3: lists.newarraylistwithcapacity 是Java中的一个方法,用于创建一个ArrayList对象并指定初始容量。 ArrayList是Java中一种动态数组,可以自动扩容以适应数据量的增加。但是,每次扩容都需要重新分配内存空间,容易造成资源浪费。因此,为了提高效率,可以通过指定初始容量来避免频繁扩容。 方法 lists.newarraylistwithcapacity 接受一个整数作为参数,用于指定ArrayList的初始容量。例如,如果我们需要创建一个长度为10的ArrayList对象,可以使用以下代码: ``` import java.util.ArrayList; import java.util.List; public class ArrayListExample { public static void main(String[] args) { List<Integer> list = new ArrayList<>(10); // 添加元素到ArrayList for (int i = 0; i < 10; i++) { list.add(i); } } } ``` 在上面的示例代码中,我们使用 ArrayList<Integer> list = new ArrayList<>(10) 来创建一个长度为10的ArrayList对象。因为我们已经知道该ArrayList将保存10个整数,因此指定初始容量为10可以避免频繁扩容,从而提高效率。 需要注意的是,指定初始容量不代表ArrayList只能保存指定数量的元素。如果需要保存更多的元素,ArrayList会自动扩容。因此,在实际使用中,我们可以根据需要适当地调整初始容量。 总之,lists.newarraylistwithcapacity 方法是Java中用于创建指定初始容量的ArrayList对象的方法。通过指定初始容量,我们可以避免频繁扩容,提高效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值