我正在开发一个Java
应用程序,其中包含许多List
- s和过程,我需要它才能执行得非常快。我想知道何时指定列表的类型元素,如果循环更快。
一个例子:
代码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);
//...
}
代码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);
//...
}
code 2
比code 1
更快吗?
答案 0 :(得分:4)
它们具有相同的运行时性能,因为Java Generics是使用类型擦除实现的。以下描述来自Java Generics的Oracle / Sun教程
https://docs.oracle.com/javase/tutorial/java/generics/erasure.html
类型删除
...
类型擦除确保不会为参数化创建新类 类型;因此,泛型不会产生运行时开销。
答案 1 :(得分:4)
它们将具有完全相同的性能,因为它们编译为完全相同的代码。这就是type erasure的工作原理:它会移除List<Foo>
List
Foo foo = list.get(i)
,并用Foo foo = (Foo) list.get(i)
替换instanceof List<Foo>
(以及类似的调用)。这就是为什么,例如,您无法询问某些内容是否为<Foo>
- 运行时缺少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);
}
}
}
信息,因为它在编译时被删除了。
您可以自己验证。如果你选择一个简单的课程,比如:
javap -c Test
您可以编译它,然后使用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
对其进行反编译,并查看这两种方法。他们会是一样的。
(String)
特别注意第31字节的checkcast操作及其注释。那是<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/bounce_interpolator" >
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromAlpha="0.0"
android:interpolator="@android:interpolator/decelerate_quad"
android:toAlpha="1.0"/>
</set>
演员。
答案 2 :(得分:2)
我希望这两个代码几乎完全相同。原因是您的代码的两个版本实际上都使用以下List
:
List<Object> list = new ArrayList<>();
在第一种情况下,Object
是默认的集合类型,在第二种情况下,List<Item>
在类型擦除后将变为List<Object>
。
答案 3 :(得分:0)
将这两个代码放在此程序中,您将自己看到结果:
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));
}
}