简体   繁体   English

Java - 新的ArrayList(List)vs empty ArrayList()+ add(element)

[英]Java - new ArrayList(List) vs empty ArrayList() + add(element)

I've learned today that you can create a new ArrayList object utilizing a static method like so: 我今天已经了解到你可以使用静态方法创建一个新的ArrayList对象,如下所示:

List<String> listDummy = Arrays.asList("Coding", "is", "fun"); 
ArrayList<String> stringList = new ArrayList<>(listDummy);

Or even more concisely: 或者更简洁:

ArrayList<String> stringList = new ArrayList<>(Arrays.asList("Coding", "is", "fun"));

My question is: How expensive is this performance-wise compared to the "traditional" way? 我的问题是:与“传统”方式相比,这种表现有多贵? (below) (下面)

ArrayList<String> stringList = new ArrayList<>();
stringList.add("Coding");
stringList.add("is");
stringList.add("fun");

I realize the upper way of creating an ArrayList includes an extra List object creation, however, I prefer the shorter and more compact syntax to an extent that I'm willing to sacrifice some performance but gotta draw the line somewhere. 我意识到创建一个ArrayList的上层方法包括一个额外的List对象创建,但是,我更喜欢更短更紧凑的语法,以至于我愿意牺牲一些性能,但必须在某处画线。

PS. PS。 leaving the type information(<>) empty in "new ArrayList<>()" is a Java SE 7 feature, not an error. 在“new ArrayList <>()”中保留类型信息(<>)为空是Java SE 7的功能,而不是错误。

Thank you beforehand for any answers! 先谢谢你的回答!

The performance difference is likely to be 30 - 300 ns depending on your system and how warmed up your code is. 性能差异可能为30 - 300 ns,具体取决于您的系统以及代码的预热程度。 I suspect the performance difference is small. 我怀疑性能差异很小。

I always say, if in doubt; 我总是说,如果有疑问; write the code as simpler and clear as you can and it will often perform ok as well. 尽可能简单明了地编写代码,并且它通常也会运行正常。

The usual add() way calls three methods. 通常的add()方式调用三个方法。

The asList() way makes an array, then does clone() on it (which does a shallow copy), then does copy all the elements manually because of this bug . asList()方式创建一个数组,然后对其执行clone() (执行浅拷贝),然后由于此错误而手动复制所有元素。 And afterwards, if you want to add another element to stringList , the array will have to be made larger and elements re-copied, because the size was exact for the elements provided. 然后,如果要向stringList添加另一个元素,则必须使该数组更大并重新复制元素,因为所提供的元素的大小是精确的。 (all this is implementation dependant and assumes Oracle JDK) (所有这些都取决于实现并假设Oracle JDK)

For three elements, the latter will be slower, but for any practical use, it will be negligible. 对于三个元素,后者将更慢,但对于任何实际使用,它将是可以忽略不计的。 For many elements, the two approaches might get equal in performance and the former one might even get slower. 对于许多元素,这两种方法在性能上可能相同,前者可能会变得更慢。

Write what you think will read the best, the performance penalty is minimal and you should not care about it until it proves itself to be bottleneck. 写下您认为最好的内容,性能损失最小,在您证明自己是瓶颈之前,您不应该关心它。


All that said, if you're after consice syntax, you could like Google Guava's Lists : 所有这一切,如果您使用consice语法,您可能会喜欢Google Guava的Lists

List<String> stringList = Lists.newArrayList("Coding", "is", "fun");

I haven't used a classic ArrayList constructor for quite a while now. 我现在已经有一段时间没有使用经典的ArrayList构造函数了。

You can do it in one line without creating additional lists: 您可以在一行中执行此操作而无需创建其他列表:

ArrayList<String> stringList = new ArrayList<>(){{
    add("Coding");
    add("is");
    add("fun");
}};

This is an anonymous class, which is a subclass of ArrayList, with an instance block. 这是一个匿名类,它是ArrayList的子类 ,带有一个实例块。

If you are not going to add /remove elements from the list after creation then the best way is not to create ArrayList at all, this will be really efficient 如果您不打算在创建后添加/删除列表中的元素,那么最好的方法是不创建ArrayList,这将非常有效

List<String> listDummy = Arrays.asList("Coding", "is", "fun"); 

otherwise new ArrayList<>(listDummy) is more efficient than manual adding elements one by one, see ArrayList(Collection) src: 否则new ArrayList<>(listDummy)比手动逐个添加元素更有效,请参阅ArrayList(Collection)src:

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);
}

it's optimized: 它被优化:

1) it creates the array of exact size 1)它创建精确大小的数组
2) it uses native copying of elements 2)它使用元素的原生复制

The list you get from Arrays.asList is already an ArrayList, so it is not necessary to wrap it with an ArrayList again: 从Arrays.asList获得的列表已经是一个ArrayList,因此没有必要再次使用ArrayList包装它:

  public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
    }

Caveat: The list is read-only, so if you need to write it, you will need to wrap it indeed using new ArrayList(..). 警告:列表是只读的,所以如果你需要编写它,你需要使用新的ArrayList(..)来包装它。

Nevertheless, I think using Arrays.asList should be better than creating a list using repeated calls of "add", because the ArrayList's internal array is initialized with the correct size. 不过,我认为使用Arrays.asList应该比使用“add”的重复调用创建列表更好,因为ArrayList的内部数组是用正确的大小初始化的。 So the best way would be 所以最好的方法是

List<String> myList= Arrays.asList("Coding", "is", "fun");
// or if you need to write the list
List<String> myList = new ArrayList(Arrays.asList("Coding", "is", "fun"));

Also this is the most readable IMHO, and readability for me always wins over very small performance gains unless you really need that extra performance. 这也是最易读的恕我直言,除非你真的需要额外的性能,否则我的可读性总是会赢得非常小的性能提升。 If you really need to do performance tuning, use a profiler. 如果您确实需要进行性能调整,请使用分析器。 The bottleneck is usually where you wouldn't expect it to be. 瓶颈通常是你不希望的。 A profiler can give you exact information about what parts of your program are slow and you can optimize them as needed. 探查器可以为您提供有关程序哪些部分较慢的确切信息,您可以根据需要对其进行优化。

The performance difference depends on size of the source array. 性能差异取决于源阵列的大小。

If you are adding items one by one multiple reallocations inside destination array will happen. 如果要逐个添加项目,则会在目标阵列中进行多次重新分配。

If you are adding whole collection at once only one allocation should be done, because the size is known beforehand. 如果要立即添加整个集合,则只应进行一次分配,因为事先已知大小。

I sometimes use a convenience function: 我有时使用便利功能:

public static <T> ArrayList<T> asArrayList(T... args) {
    ArrayList<T> list = new ArrayList<T>(args.length);
    Collections.addAll(list, args);
    return list;
}

This is a bit quicker than the Arrays.asList route. 这比Arrays.asList路由快一点。 (Not that it would ever really matter for hard-coded lists.) (并不是说硬编码列表真的很重要。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM