Reputation: 746
I am developing a Java
application with many List
-s and procedures and I need it to execute very fast. I would like to know when I specify the type elements of a list, if the loops are faster.
An example:
Code 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:
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
?
Upvotes: 2
Views: 119
Reputation: 43391
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)
. 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.
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. 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. That's the (String)
cast.
Upvotes: 4
Reputation: 7152
They have the same run-time performance, because Java Generics are implemented using type erasure. The following description come from the Oracle/Sun tutorial on Java Generics
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.
Upvotes: 4
Reputation: 299
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));
}
}
Upvotes: 0
Reputation: 520968
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<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.
Upvotes: 2