[英]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 2
比code 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.