1.Why do they assign an ArrayList to List?.
Assigning List interface is like assigning a Child class object to parent class variable.Here List interface is assigned to ArrayList Class.

List is an interface.The intention of Using a Interface is if you decide to change your implementation later while you code you can change it at the point of creation Like one below

 List<Fruits> arrFruits = new ArrayList<Fruits>();

converted to

 List<Fruits> arrFruits = new LinkedList<Fruits>(); 

2.What is java.util.ConcurrentModificationException
The below code Generate java.util.ConcurrentModificationException

 List<Fruits> arrFruits = new ArrayList<Fruits>();

 Fruits objApple  = new Apple();
 Fruits objOrange = new Orange();
 Fruits objMango  = new Mango();

 arrFruits.add(objApple);
 arrFruits.add(objOrange);
 arrFruits.add(objMango);

 List<Fruits> arrNewFruits = arrFruits.subList(0, 1);
 arrFruits.retainAll(arrNewFruits); 

In your above code examples you I have a big list and the sub-list in reverse order.
When I invoke retainAll() on the sub-list, no modifications will occur.
This is because each element in the sub-list is in the big list.
If no modification occurs, no ConcurrentModificationException will be thrown.


If I reverse the order and invoke retainAll() on the big list, it will get mutated.
This is because not every item in the big list is in the sub-list.
When I remove an element from the big list, a ConcurrentModificationException is thrown.
This is because I cannot mutate a list while iterating over it.

The iteration takes place in the retainAll() method.
In my code, the list argument happens to reference the same list that’s being modified.
This is because of the way List.subList() works:

arrNewFruits.retainAll(arrFruits) //This Works

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.

I should create a new list from the sub-list if there is a chance that either list will get modified while one of the lists is being iterated over.

I can create a new list from the sub-list like below

List<Foo> freshList = new ArrayList<Foo>(bigList.subList(0,2));

Now I can iterate and mutate.

3.In the below code if you try to add number 5 to List it will result in runtime Exception java.lang.UnsupportedOperationException

 List<Integer> arrNums = Arrays.asList(1,2,3,4);

 arrNums.add(5);

Arrays.asList(1,2,3,4) creates a list on an array whose size cannot be changed.does not convert array but ‘represents’ it like a List.But array is under the hood with all its properties like a fixed number of elements. That way we can use and access an array through the List interface.

4.

public static <T> List<T> asList(T... a)

Documentation states that asList returns an object that implements interface java.util.List, nowhere does it says it will return an instance of class java.util.ArrayList.

5.If you want a List generated from asList() method but still want to use add Method

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3,4));

6.I am having a Primitive array as below. Using Arrays.asList method does not return boxed Integer List value.

int[] nums = new int[] { 1, 2, 3 };
Arrays.asList(nums)

One way is to iterate over the primitive array and add elements to Integer ArrayList Manually.

List<Integer> items = new ArrayList<Integer>();

for (Integer item: nums) 
{
  items.add(item);
}

Other way is to use streams as below

int[] nums = new int[] { 1, 2, 3 };
Arrays.stream(nums)
      .boxed()
      .collect(Collectors.toList());

7.Return Types in ArrayList add Method

Test.java

public class Test 
{
  public static void main(String[] args) 
  {		
    List arraList = new ArrayList<String>();
    System.out.println(arraList.add("Mugil"));
  }
}

Output

True

But the below add method is of void return type

public class Test 
{
  public static void main(String[] args) 
  {		
    List arraList = new ArrayList<String>();
    System.out.println(arraList.add(1, "Mugil"));
  }
}

Why it is So?
Collection.add is a pretty generic method (widely applicable). As such, they wanted a return value that would apply generally.

Some classes (like ArrayList) always accept elements irrespective of element already in the list(duplicate element), and so will always return true. In these cases, a return type of void is more then enough.

If a collection refuses to add a particular element for any reason other than that it already contains the element say Set, it must throw an exception (rather than returning false).

So if it returns true, the element was added, if it returns false the element was already there (such as in a Set) and in other cases an exception needs to be thrown (for example if a Collection would limit its size and not block).

Differences is that the contract for add(E) is defined in Collection, whereas add(int index, E e) is defined in the List interface (and doesn’t need to return anything). It could return true as well, but it would be useless. The other method has to return true, because otherwise it would break the contract for Collection.

The way the Set Collection could have been is

if (!set.contains(item)) 
{
    set.add(item);
    itemWasAdded(item);
}

The extra checking of Contains is skipped in below actual java code design

if (set.add(item)) 
{
    itemWasAdded(item);
}

But this check-then-act behavior isn’t thread safe, which can be crucial in multithreaded applications. For instance, it could be that another thread added an equal item between you checking set.contains(item) and the set.add(item) in the first code snippet. In a multithreaded scenario, those two actions really need to be a single, atomic action; returning boolean from the method makes that possible.

8.Iterator vs ListIterator
When you are simple moving through List but you are not modifying the List object foreach is more efficient.In case you want to perform operations on each element of list individually taking out the element in such case use Iterator.

List<Fruits> arrFruits = new ArrayList<Fruits>();
Iterator<Fruits> itFrt = arrFruits.iterator();

while(itFrt.hasNext())
{
 Fruits frt = itFrt.next();
 System.out.println(frt);
}

ListIterator

  • While using Iterator in particular to List using a ListIterator is more powerful over Iterator.
  • ListIterator is bidirectional
  • It also keep track of Indexes of next and previous elements
  • It can replace last element it visited using set method
 List<fruits> arrFruits     = fruits.arrayList(5);
 ListIterator<fruits> itFrt = arrFruits.listIterator();

 while(itFrt.hasNext())
 {
   System.out.println(it.next()); 
   System.out.println(it.nextIndex()); 
   System.out.println(it.previousIndex()); 
 }

Leave a reply