Friday, September 15, 2006

Java Tutorials: ArrayList or Vector?

This is one of the famous questions that a Java beginner has in his mind. This is also a famous question asked in interviews. Following are the differences between ArrayList and Vector.

1. Vectors and Hashtable classes are available from the initial JDK 1.0. But, ArrayList and HashMap are added as a part of new Collections API since JDK 1.2.

2. Vectors and Hashtable are synchronized where as ArrayList and HashMap are unsynchronized.

When to use Vector? When to use ArrayList?

1. ArrayList is faster when compared to Vector since ArrayList is unsynchronized. So, if the List will be modified by only one thread, use ArrayList. If the list is a local variable, you can always use ArrayList.
2. If the List will be accessed by multiple threads, always use Vector, otherwise you should take care of synchronization manually.

To visualize the problem with synchronization, try the following code.

There is a Producer class that adds 5000 elements to the List (ArrayList/Vector). Another class, Consumer class removes 5000 elements from the same list. There are around 10 producer threads and 10 consumer threads.



class Producer implements Runnable {

private List list;

public Producer(List pList) {
list = pList;
}

public void run() {
System.out.println("Producer started");
for (int i = 0; i < 5000; i++) {
list.add(Integer.toString(i));
}
System.out.println("Producer completed");
}

}




class Consumer implements Runnable {
private List list;

public Consumer(List pList) {
list = pList;
}

public void run() {
System.out.println("Consumer started");
for (int i = 0; i < 5000; i++) {
while (!list.remove(Integer.toString(i))) {
// Just iterating till an element is removed
}

}
System.out.println("Consumer completed");
}
}



public class ListTest {

public static void main(String[] args) throws InterruptedException {
// List list = new Vector();
List list = new ArrayList();

for (int i = 0; i < 10; i++) {
Thread p1 = new Thread(new Producer(list));
p1.start();
}

for (int i = 0; i < 10; i++) {
Thread c1 = new Thread(new Consumer(list));
c1.start();
}
Thread.yield();

while (Thread.activeCount() > 1) {
Thread.sleep(100);
}

System.out.println(list.size());

}

}



Try running the program with ArrayList. You can see a number of ArrayIndexOutOfBoundException, Consumer threads will still keep waiting for more elements which wont be added because the Producer has terminated after throwing the Exception.

Now, change the line,
List list = new ArrayList();

to
List list = new Vector();

and run the program.

Now you can see a proper result.

This clearly explains why you should use Vector class when there are multiple threads in the system.

In this program, even if you remove the Consumer class and Consumer thread, you can see that the Producer will themselves throw Exception.

This is because, while adding an element to the ArrayList, it checks for the size of the Array. If the array size is not sufficient, a new array will be created, the elements will be copied to the new array. If the context switching if Threads happen at this place also, we will get ArrayIndexOutOfBoundException, or sometimes, you maynot get any Exception, but some elements will be missing, and many unexpected behaviours.

So always use Vector if there are multiple threads. The same rule applies to HashMap vs Hashtable, StringBuilder vs StringBuffer

Summary:
1. Use Vector if there are multiple threads and ArrayList if there is only a single thread.
2. Use Hashtable if there are multiple threads and HashMap if there is only a single thread.
3. Use StringBuffer if there are multiple threads and StringBuilder if there is only a single thread.

11 Comments:

Anonymous Anonymous said...

Then deart skelton coder what do you think is best fit for web-apps which is multithreaded nd speed is also desired....

10:37 AM  
Blogger Jayaprabhakar said...

In my opinion,
Correctiveness is more important than Performance. So,
Vector will be the right choice.

To allow the functionality to be more flexible, always program for interface, not for implementation.

Eg: Prefer using,
List list = new Vector()
or
List list =
Collections.synchronizedList(new ArrayList);

instead of
Vector list = new Vector();

The first two allows the code to be more flexible.

9:47 PM  
Blogger Lie said...

Writing correct code is more important than writing fast code. There is the age-old saying: "Optimizing correct code is easier than correcting optimized code."

So always use Vector unless you are sure that ArrayList can safely replace it and you really need the squeeze performance (in most case, a slower code is more acceptable than a late project).

8:54 AM  
Blogger Steven J. Luke said...

I stumbled upon this via reference on a JavaRanch forum. I disagree nearly completely with the choice of ever using Vector. It is old, legacy code which was retrofitted incompletely into the collections API.

To get the same functionality as Vector using pure Collections interface, use the Collections.synchronizedList() method referred to by Jayaprabhakar, or use one of the Collections provided in the (java 1.5+ only) java.util.concurrent package.

Also, List doesn't solve all collection needs. A better collection choice is probably in order for your Producer/Consumer scenario - probably a Queue, and most likely a BlockingQueue would be better (again, both Java 1.5+.) Pre-Java 1.5 you pretty much are stuck with a List implementation.

Also, don't forget that Vector does not remove the need to synchronize completely. You still don't get sequential consistency with a Vector (i.e., moving from index 1 to index 2 may skip objects, or move you backwards if another if another thread is working on the same Vector). To get sequential consistency you need to externally synchronize any loops/iterations or swap to one of the java.util.concurrent collections.

7:57 AM  
Blogger Params said...

Loved the post! Very informative.. Thanks!

4:53 AM  
Blogger Params said...

Loved the post! Very informative.. Thanks!

4:53 AM  
Blogger CRAZY said...

Easily understandable..

9:49 AM  
Blogger Deepak said...

Thanks for an excellent article. I agree with Jayaprabhakar and Steven. You shouldn't use the Vector as its legacy and also I would like to add that it is very slow in performance. The Collections.synchronizedList performs far better than the Vector and gives the reliable list functionality required from a synchronized lists.

3:05 PM  
Blogger GT said...

nice article....

8:53 PM  
Blogger Javin Paul said...

good comparison, but with Java 5 more alternatives are available including CopyOnWriteArraylist which is highly optimized for many reader and single writer scenario and we should be using those. I have also blogged about Java Arraylist in Java 5 some time back , may be you find interesting.

8:18 AM  
Blogger Aftab said...

Welldone and thnx very comprehensive and informative Keepit up dude.

6:59 AM  

Post a Comment

Links to this post:

Create a Link

<< Home