Q&A : ArrayList

Q :Write a method that takes a List of elements and returns a new List containing the same elements in the same order with the second and subsequent occurrences of any duplicate elements removed.

A: One of the answer is to use LinkedHashSet as follows:


public static <E> List<E> withoutDuplicates(List<E> original) {
 return new ArrayList<E>(new LinkedHashSet<E>(original));
 }

 public static void withoutDuplicatesTest(){
 List<String> list1 = Arrays.asList("test1", "test2", "test1", "test3","test2", "test4");
 System.out.println(list1);
 System.out.println(withoutDuplicates(list1));
 }

Output:


[test1, test2, test1, test3, test2, test4]
[test1, test2, test3, test4]

Q : Suppose you have 3 list, How will you get all the common elements in each.

A : Use retainAll() method of collection.


public static void retainAllTest(){
 List<String> list1 = new ArrayList<String>(Arrays.asList("test1", "test2", "test3"));
 List<String> list2 = new ArrayList<String>(Arrays.asList("test1", "test2", "test4","test5"));
 List<String> list3 = new ArrayList<String>(Arrays.asList("test1", "test2", "test4", "test6"));
 System.out.println("list2 before retaing=>"+list2);
 list2.retainAll(list3);
 System.out.println("list2 after retaing elements of list3=>"+list2);
 list1.retainAll(list2);
 System.out.println("list1 after retaing elements of list2=>"+list1);
 }

Output:


list2 before retaing=>[test1, test2, test4, test5]
list2 after retaing elements of list3=>[test1, test2, test4]
list1 after retaing elements of list2=>[test1, test2]

Notice that we are using new ArrayList<String>(Arrays.asList(“test1”, “test2”, “test3”)); Instead of what we did previously, simply just Arrays.asList(“test1”, “test2”, “test3”)

This is because  – Array.asList() wraps an array in the list interface. The list is still backed by the array. Arrays are a fixed size – they don’t support adding or removing elements, so the wrapper can’t either. You can’t add to it; you can’t remove from it. So create a new implementation instead.

QHow to sort ArrayList in Descending Order in Java.

A: ArrayList can also be sorted in descending or reverse order by using Collections.reverseOrder(list) and Collection.reverseOrder(list,Comparator cmp).


public static void reverseOrderTest(){
 List unsortedList = Arrays.asList("abc", "bcd", "ade", "cde");
 System.out.println("Arraylist before: " + unsortedList);
 Collections.sort(unsortedList, Collections.reverseOrder());
 System.out.println("Arraylist in descending order: " + unsortedList);

}

Output:


Arraylist before: [abc, bcd, ade, cde]
Arraylist in descending order: [cde, bcd, ade, abc]

Q : How to sort ArrayList of String  in Case insensitive Order.

A : ArrayList  of String can also be sorted with case insensitive comparison. String class defines a convenient case insensitive comparator which can be accessed directly like String.CASE_INSENSITIVE_ORDER . if you pass this comparator to ArrayList.sort() which contains String then those will be sorted accordingly.


public static void caseInsensitiveTest(){
 List<String> unsortedList = Arrays.asList("abc", "bcd", "ABC", "BCD");
 System.out.println("ArrayList before case insensitive sort: " + unsortedList);
 Collections.sort(unsortedList, String.CASE_INSENSITIVE_ORDER);
 System.out.println("ArrayList after case insensitive sort: " + unsortedList);
 }

Output:


ArrayList before case insensitive sort: [abc, bcd, ABC, BCD]
ArrayList after case insensitive sort: [abc, ABC, bcd, BCD]

Q : What are bounded and unbounded wildcards in generics.

A : Bounded and unbounded wildcards in generics are used to bound any Type. Type can be upper bounded by using <? extends T> where all Types must be sub-class of T or lower bounded using <? super T> where all Types required to be super class of T.

Single <?> is called an unbounded wildcard in generic and it can represent any type, similar to Object in Java. For example  List<?> can represent any List e.g. List<String> or List<Integer> its provides highest level of flexibility on passing method argument.

Lets see this by an example :

Suppose there is a class heirachy like :

Employee

SoftwareDeveloper extends Employee

JavaDeveloper extends SoftwareDeveloper


public static void testExtendsBound(List<? extends SoftwareDeveloper> slist) {}

public static void testSuperBound(List<? super SoftwareDeveloper> slist) {}

public static void testUnBound(List<?> slist) {}

public static void boundedAndUnboundedTest() {
List<SoftwareDeveloper> slist = new ArrayList<SoftwareDeveloper>();
List<JavaDeveloper> jlist = new ArrayList<JavaDeveloper>();
List<Employee> elist = new ArrayList<Employee>();

testExtendsBound(slist);// OK
testExtendsBound(jlist);// OK
testExtendsBound(elist);// Compile Error As only 'subclass' can be passed with extends

testSuperBound(slist);// OK
testSuperBound(jlist);// Compile Error As only 'superclass' can be passed with extends
testSuperBound(elist);// OK

List<Object> anyList = new ArrayList<Object>();

testUnBound(slist);// OK
testUnBound(jlist);// OK
testUnBound(elist);// OK
testUnBound(anyList);// OK

}

Q : Can you pass List<String> to a method which accepts List<Object> ?

A : In first glance it looks like : String is Object so List<String> can be used where List<Object> is required but this is not true.

It will result in compilation error. This is because List<Object> can store any any thing including String, Integer etc but List<String> can only store Strings. Similary for any other cases also.

Q: Difference between fail-fast Iterator vs fail-safe Iterator in Java.

A : As name suggest fail-fast Iterators fail as soon as they realized that structure of Collection has been changed since iteration has begun. Structural changes means adding, removing or updating any element from collection while one thread is Iterating over that collection. fail-fast behavior is implemented by keeping a modification count and if iteration thread realizes the change in modification count it throwsConcurrentModificationException.

Java doc says this is not a guaranteed behavior instead its done of “best effort basis”, So application programming can not  rely on this behavior. Also since multiple threads are involved while updating and checking modification count and this check  is done without synchronization, there is a chance that Iteration thread still sees a stale value and might not be able to detect any change done by parallel threads.

Contrary to fail-fast Iterator, fail-safe iterator doesn’t throw any Exception if Collection is modified structurally

while one thread is Iterating over it because they work on clone of Collection instead of original collection and that’s why they are called as fail-safe iterator. Iterator of CopyOnWriteArrayList is an example of fail-safe Iterator also iterator written by ConcurrentHashMap keySet is also fail-safe iterator and never throw ConcurrentModificationException in Java.

Q: How to create read only List, Map and Set in Java

A : Using Collections.unmodifiableList()


public static void unmodifiableListTest() {
List<String> list1 = new ArrayList<String>(Arrays.asList("test1", "test2", "test3"));
System.out.println("list1 ORIGINAL=>"+list1);

List<String> list2 = Collections.unmodifiableList(list1);//list2 got new cloned object
System.out.println("list2=>"+list2);

list1.add("test4"); //we can still modify list1
System.out.println("list1 AFTER=>"+list1);

list2.add("test4"); //ADD/remove/set etc NOT ALLOWED will throw runtime UnsupportedOperationException

}

Output:


list1 ORIGINAL=>[test1, test2, test3]
list2=>[test1, test2, test3]
list1 AFTER=>[test1, test2, test3, test4]
Exception in thread "main" java.lang.UnsupportedOperationException

Q : How to synchronize ArrayList.

A : There are two ways to synchronize explicitly:

  • Using Collections.synchronizedList() method
  • Using thread-safe variant of ArrayList: CopyOnWriteArrayList

First let’s see Some difference between ArrayList and CopyOnWriteArrayList in Java , which is another implementation of List interface :

  • First and foremost difference between CopyOnWriteArrayList and ArrayList in Java is that CopyOnWriteArrayList is a thread-safe collection while ArrayList is not thread-safe and can not be used in multi-threaded environment.
  •  Second difference between ArrayList and CopyOnWriteArrayList is that Iterator of ArrayList is fail-fast and throwConcurrentModificationException once detect any modification in List once iteration begins but Iterator ofCopyOnWriteArrayList is fail-safe and doesn’t throw ConcurrentModificationException.
  • Third difference between CopyOnWriteArrayList vs ArrayList is that Iterator of former doesn’t support remove operation while Iterator of later supports remove() operation.

public static void synchronizingArrayListTest() {
List<String> syncList1 = Collections.synchronizedList(new ArrayList<String>());
syncList1.add("one");
syncList1.add("two");
syncList1.add("three");

// when iterating over a synchronized list, we need to synchronize access to the synchronized list
synchronized (syncList1) {
Iterator<String> failFastIterator = syncList1.iterator();
while (failFastIterator.hasNext()) {
System.out.println("item1: " + failFastIterator.next());
failFastIterator.remove();
}
}
System.out.println("syncList1: " + syncList1);

CopyOnWriteArrayList<String> syncList2 = new CopyOnWriteArrayList<String>();
syncList2.add("one");
syncList2.add("two");
syncList2.add("three");

//Synchronized block is not required in this method
Iterator<String> failSafeIterator = syncList2.iterator();
while (failSafeIterator.hasNext()){
System.out.println("item2: " + failSafeIterator.next());
//failSafeIterator.remove(); //Not supported by CopyOnWriteArrayList runtime error
}
System.out.println("syncList2: " + syncList2);

}

Output:


item1: one
item1: two
item1: three
syncList1: []
item2: one
item2: two
item2: three
syncList2: [one, two, three]

Notice that  in Collections.synchronizedList() method, the important point to note here is that iterator should be in synchronized block in this type of synchronization. Iterator of synchronizedList is not (and can’t be) synchronized, you need to synchronize on the list manually while iterating. However, Collections.synchronizedList(). It implements a copy-on-write semantic and therefore doesn’t require synchronization.

Q : What is the difference between Synchronized Collection classes and Concurrent Collection Classes ?

A : The synchronized collections classes, Hashtable and Vector, and the synchronized wrapper classes, Collections.synchronizedMap and Collections.synchronizedList, provide a basic conditionally thread-safe implementation of Map and List.

However, several factors make them unsuitable for use in highly concurrent applications — their single collection-wide lock is an impediment to scalability and it often becomes necessary to lock a collection for a considerable time during iteration to prevent ConcurrentModificationException.

The ConcurrentHashMap and CopyOnWriteArrayList implementations provide much higher concurrency while preserving thread safety, with some minor compromises in their promises to callers. ConcurrentHashMap and CopyOnWriteArrayList are not necessarily useful everywhere you might use HashMap or ArrayList, but are designed to optimize specific common situations. Many concurrent applications will benefit from their use.

Q : How to Clone Collection in Java – Deep copy of ArrayList.

A : Copy constructor of Collection in Java only provides shallow copy and not deep copy, which means objects stored in both original List and cloned List will be same and point to same memory location in Java heap. Lets see this by an example:


package mynotes.QandA;

public class Employee {

private int id;
private String name;
public Employee(){}
public Employee(int id,String name){
this.id=id;
this.name=name;
}
@Override
public String toString() {
return "id=>"+this.id+"name=>"+this.name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}


public static void cloningArrayListUsingCopyConstructor() {
List<Employee> emp1=new ArrayList<Employee>();
emp1.add(new Employee(1,"asdfg"));
emp1.add(new Employee(2,"qwerty"));
System.out.println("emp1 list->"+emp1);
List<Employee> emp2=new ArrayList<Employee>(emp1);
emp2.get(0).setName("zxcv");
System.out.println("emp1 list after emp2 list changed its object"+emp1);
}

Output:


emp1 list->[id=>1name=>asdfg, id=>2name=>qwerty]
emp1 list after emp2 list changed its object[id=>1name=>zxcv, id=>2name=>qwerty]

In order to deep clone, we need to override clone() method in Employee class. While overriding clone through eclipse : following code will be generated


@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}

Make the class implements Cloneable and Changing to our requirements:


@Override
protected Employee clone() {
Employee clone = null;
try {
clone = (Employee) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e); // won't happen
}
return clone;
}

Now we will iterate through emp1 and add in emp2 using above clone() implementation.


public static void cloningArrayListUsingClonning() {
List<Employee> emp1=new ArrayList<Employee>();
emp1.add(new Employee(1,"asdfg"));
emp1.add(new Employee(2,"qwerty"));
System.out.println("emp1 list->"+emp1);

List<Employee> emp2=new ArrayList<Employee>(emp1.size());

Iterator<Employee> iterator = emp1.iterator();
while(iterator.hasNext()){
emp2.add(iterator.next().clone());
}

emp2.get(0).setName("zxcv");
System.out.println("emp1 list after emp2 list changed its object"+emp1);
}

Output:


emp1 list->[id=>1name=>asdfg, id=>2name=>qwerty]
emp1 list after emp2 list changed its object[id=>1name=>asdfg, id=>2name=>qwerty]

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: