Juan Camacho
Juan Camacho

Reputation: 746

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. 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

Answers (4)

yshavit
yshavit

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

leeyuiwah
leeyuiwah

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

Manish Sakpal
Manish Sakpal

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

Tim Biegeleisen
Tim Biegeleisen

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

Related Questions