简体   繁体   English

是列表 <Item> 比列表更快?

[英]Is List<Item> faster than List?

I am developing a Java application with many List -s and procedures and I need it to execute very fast. 我正在开发一个包含许多List -s和过程的Java应用程序,我需要它来执行得非常快。 I would like to know when I specify the type elements of a list, if the loops are faster. 我想知道何时指定列表的类型元素,如果循环更快。

An example: 一个例子:

Code 1: 代码1:

List list = new ArrayList();
Item item;
list.add(...);
list.add(...);
list.add(...);
int t = list.size();
for(int i = 0; i < t; i++){
    item = (Item)list.get(i);
    //...
}

Code 2: 代码2:

List<Item> list = new ArrayList<Item>();
Item item;
list.add(...);
list.add(...);
list.add(...);
int t = list.size();
for(int i = 0; i < t; i++){
    item = list.get(i);
    //...
}

Is code 2 faster than code 1 ? code 2code 1快吗?

They have the same run-time performance, because Java Generics are implemented using type erasure. 它们具有相同的运行时性能,因为Java Generics是使用类型擦除实现的。 The following description come from the Oracle/Sun tutorial on Java Generics 以下描述来自Java Generics的Oracle / Sun教程

https://docs.oracle.com/javase/tutorial/java/generics/erasure.html https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

Type Erasure 类型擦除

... ...

Type erasure ensures that no new classes are created for parameterized types; 类型擦除确保不为参数化类型创建新类; consequently, generics incur no runtime overhead . 因此,泛型不会产生运行时开销

They will have the exact same performance, because they compile to the exact same code. 它们将具有完全相同的性能,因为它们编译为完全相同的代码。 That's how type erasure works: it removes all your List<Foo> with List , and replaces Foo foo = list.get(i) (and similar calls) with Foo foo = (Foo) list.get(i) . 这就是类型擦除的工作原理:它用List删除所有List<Foo> ,并用Foo foo = (Foo) list.get(i)替换Foo foo = list.get(i) (以及类似的调用Foo foo = (Foo) list.get(i) That's why, for instance, you can't ask if something is instanceof List<Foo> — the <Foo> information is missing at runtime, since it was erased at compile-time. 这就是为什么,例如,你无法询问是否有某个instanceof List<Foo>instanceof List<Foo> - 运行时缺少<Foo>信息,因为它在编译时被删除了。

You can verify this for yourself. 您可以自己验证这一点。 If you take a simple class, like: 如果你参加一个简单的课程,比如:

public class Test {
  public void raw() {
    String s;
    List list = new ArrayList();
    for (int i = 0, t = list.size(); i < t; i++) {
      s = (String) list.get(i);
    }
  }

  public void generic() {
    String s;
    List<String> list = new ArrayList<>();
    for (int i = 0, t = list.size(); i < t; i++) {
      s = list.get(i);
    }
  }
}

You can compile it, then decompile it using javap -c Test and take a look at both methods. 您可以编译它,然后使用javap -c Test对其进行反编译,并查看这两种方法。 They'll be the same. 他们会是一样的。

Code:
   0: new           #2                  // class java/util/ArrayList
   3: dup
   4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
   7: astore_2
   8: iconst_0
   9: istore_3
  10: aload_2
  11: invokeinterface #4,  1            // InterfaceMethod java/util/List.size:()I
  16: istore        4
  18: iload_3
  19: iload         4
  21: if_icmpge     41
  24: aload_2
  25: iload_3
  26: invokeinterface #5,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
  31: checkcast     #6                  // class java/lang/String
  34: astore_1
  35: iinc          3, 1
  38: goto          18
  41: return

Note in particular the checkcast op at byte 31, with its comment. 请特别注意第31字节的checkcast操作及其注释。 That's the (String) cast. 那是(String)演员。

I expect these two codes to perform almost identically. 我希望这两个代码几乎完全相同。 The reason is that both versions of your code will actually use the following List : 原因是您的代码的两个版本实际上将使用以下List

List<Object> list = new ArrayList<>();

In the first case, Object is the default type of collection, and in the second case, List<Item> will become List<Object> after type erasure. 在第一种情况下, Object是默认的集合类型,在第二种情况下, List<Item> List<Object>在类型擦除后将变为List<Object>

Put these both codes in this program, you will see the result yourself: 将这两个代码放在这个程序中,您将自己看到结果:

 class Longest
 {
     public static void main(String[] args)
     {
            long start,end;

            start=System.currentTimeMillis();

            //Paste your above code here

            end=System.currentTimeMillis();

            System.out.println("Take taken by above code to execute:"+(end-start));
     }
   }

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

相关问题 有没有一种更快的方法来检查列表中的某个项目是否大于,小于或等于某个数字? - Is there a faster way to check if an item in a list if it is greater than, less than, equal to a certain number? 添加与列表其余部分不同的列表项 - Add a list item that is different than the rest of a list 为什么过滤未排序的列表比过滤排序列表更快 - Why filtering an unsorted list is faster than filtering a sorted list 为什么迭代List会比索引更快? - Why would iterating over a List be faster than indexing through it? 为什么数组列表比LIFO行为的链接列表更快? - Why is Array Lists faster than a Linked List for LIFO behaviour? 为什么哈希集的性能比列表更快? - Why the hashset's performance is way faster than list? 为什么instanceof和迭代单个列表比几个专用列表更快? - Why instanceof and iterating single list is faster than several specialized lists? 在列表中间插入的情况下,LinkedList 真的比 ArrayList 快吗? - Is LinkedList really faster than ArrayList in the case of insertion in the middle of list? 有没有办法比 Java 中的 O(n) 更快地获取列表的最后一个元素? - Is there a way to get the last element of a list faster than O(n) in Java? JMH - List#addAll 比 ArrayList#new 快吗? - JMH - List#addAll faster than ArrayList#new?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM