Collections in Java

Overview

Array

An Array is an indexed collection of fixed number of Homogenous data elements.
The main advantage of arrays is we can represent multiple values by using single variable so that readability of the code will be improved. 

Limitations of Arrays

  • Arrays are fixed in size i.e. once we create an array there is no chance of increasing or decreasing the size based on our requirement. Due to this, to use arrays concept compulsory we should know the size in advance which may not be possible always.
  • Array can hold only homogenous data type elements.
 Student[] students = new Student[1000];
students[0] = new Student("Vim Payne", 18, 20, 540);
/* Prompts a compile time error: Incompatible types found: Teacher required: Student */
students[
1] = new Teacher("Vim Payne", 18, "St. Theressa School", "9A");
  • We can solve the above problem by using Object type arrays.
 Object[] students = new Object[1000];
students[0] = new Student("Vim Payne", 18, 20, 540);
students[1] = new Teacher("Vim Payne", 18, "St. Theressa School", "9A");
  • Arrays is not implemented based on some standard data structure and hence readymade method support is not available. For every requirement we have to write the code explicitly which increases complexity of programming. 
  • To overcome the above problems of arrays we should go for Collections concept.

Differences between Arrays and Collections

  • Arrays are fixed in size i.e. once we create an array we can't increase or decrease the size based on our requirements. But Collections are growable in nature i.e. based on our requirement we can increase or decrease the size.
  • With respect to memory, Arrays are not recommended to use but Collections are recommended to use.
  • With respect to performance, Arrays are recommended to use but Collections are not recommended to use.
  • Arrays can hold only homogenous data type elements but Collections can hold homogenous and heterogenous data type elements.
  • There is not under lying data structure for Arrays and hence readymade method support is not available. For every requirement, we have to write the code explicitly which increases complexity of programming. Every Collection class is implemented based on some data structure and hence for every requirement readymade method support is available. Being a programmer we can use these methods directly and we are not responsible to implement those methods.
  • Arrays can hold both primitives and objects but Collections can hold only objects.

Collections

If we want to represent a group of individual objects as a single entity then we should go for Collection. Some advantages of Collections are listed below:
  • Collections are growable in nature i.e. based on our requirements we can increase or decrease the size of a collection. 
  • Collections can hold both homogenous and heterogenous elements.
  • Every collection class is implemented based on some standard data structure. Hence for every requirement readymade method support is available.
  • Being a programmer we are responsible to use those methods and we are not responsible to implement those methods.

Collection Framework

It contains several classes and interfaces which can be used to represent a group of individual objects as a single entity.

9 Key Interfaces of Collection Framework:

  1. Collection
  2. List
  3. Set
  4. SortedSet
  5. NavigableSet
  6. Queue
  7. Map
  8. SortedMap
  9. NavigableMap

Collection(I)

  • If we want to represent a group of individual objects as a single entity then we should go for Collection.
  • Collection interface defines the most common methods which are applicable for any collection object.
    • add(Object o)
    • addAll(Collection c)
    • remove(Object o)
    • removeAll(Collection c)
    • clear()
    • retainAll(Collection c)
    • contains(Object o)
    • containsAll(Collection c)
    • isEmpty()
    • size()
  • In general Collection interface is considered as Root interface of Collection Framework. 
  • There is no concrete class which implements Collection interface directly.
 public class CollectionMain {
public static void main(String[] args) {
Collection<String> superHero = new LinkedList<>();
superHero.add("Spider Man");
superHero.add("Iron Man");
superHero.add("Super Man");

Collection<String> superHeroine = new ArrayList<>();
superHeroine.add("Wonder Woman");
superHeroine.add("Black Widow");

Collection<String> mutants = new ArrayList<>();
mutants.addAll(superHero);
mutants.addAll(superHeroine);

mutants.forEach(hero -> {
System.out.println(hero);
});
System.out.println("=========================");
mutants.remove("Iron Man");
/* This is lambda expression */
mutants.forEach(System.out::println);
}
}
  • Below illustration shows the Interfaces and Classes that belongs to Collection.

Difference Between Collection and Collections

  • Collection is an Interface, if we want to represent a group of individual objects as a single entity then we should go for Collection. 
  • Collections is an utility class present in java.util package to define several utility methods for collection objects like sorting, searching etc.

List(I)

  • It is the Child interface of Collection.
  • If we want to represent a group of individual objects as a single entity where duplicates are allowed and insertion order must be preserved then we should go for List Interface.
  • We can preserve insertion order via index and we can differentiate duplicate objects by using index. Hence index will play very important role in List.
  • List Interface defines the following specific methods.
    • void add(int index, Object o)
    • boolean addAll(int index, Collection c)
    • Object get(int index)
    • Object remove(int index)
    • Object set(int index, Object new): This is used to replace the element present at specified index with the provided Object and returns old Object.
    • int indexOf(Object o): It returns the index of first occurrence of Object 'o'.
    • int lastIndexOf(Object o)
    • ListIterator listIterator()
  • The under laying data structure is 
    • Resizable array or growable array.
    • Duplicate objects are allowed.
    • Insertion Order is preserved.
    • Heterogenous Objects are allowed (Except TreeSet and TreeMap, everywhere Heterogenous Objects are allowed).
    • null insertion is possible.
  • Note: In 1.2 version Vector and Stack classes are re-engineered / modified to implement List interface.

ArrayList

  • Constructors
 ArrayList l = new ArrayList();
    • In the above code creates an empty ArrayList Object with default initial capacity i.e. 10.
    • Once ArrayList reaches it's max capacity then a new ArrayList object will be created with 
 int initialCapacity = 30;
ArrayList l = new ArrayList(initialCapacity);
    • The above code creates an empty ArrayList Object with specified initial capacity.
 Collection c = new ArrayList();
ArrayList l = new ArrayList(c);
    • Creates an equivalent ArrayList Object for the given Collection 'c'.
 public class ListMain {
public static void main(String[] args) {
ArrayList l = new ArrayList();
l.add("A");
l.add(10);
l.add("A");
l.add(null);
System.out.println(l);
l.remove(1);
System.out.println(l);
l.add(2,"M");
l.add("N");
System.out.println(l);
}
}
 [A, A, M, null, N]
    • Hello World
  • Usually we can use Collections to hold and transfer objects from one location to another location (Container). To provide support for this requirement every Collection class by default implements Serializable and Cloneable Interfaces.
  • ArrayList and Vector classes implements RandomAccess Interface so that any random element we can access with the same speed.
  • RandomAccess: RandomAccess Interface present in java.util package and it doesn't contain any methods. It is a Marker Interface, where required ability will be provided automatically by the JVM.
 ArrayList arrayList = new ArrayList<>();
LinkedList linkedList = new LinkedList();
System.out.println(arrayList instanceof Serializable); // true
System.out.println(linkedList instanceof Serializable); // true
System.out.println(arrayList instanceof Cloneable); // true
System.out.println(linkedList instanceof Cloneable); // true
System.out.println(arrayList instanceof RandomAccess); // true
System.out.println(linkedList instanceof RandomAccess); // false
  • ArrayList is the best choice if our frequent operation is retrieval operation because ArrayList implements RandomAccess Interface.
  • ArrayList is the worst choice if our frequent operation is insertion or deletion in the middle.

Different Between ArrayList and Vector

  • Every method present in the ArrayList is non-synchronized whereas, every method present in the Vector is synchronized.
  • At a time, multiple threads are allowed to operate an ArrayList Object and hence it is not Thread-Safe. At ta time, only one thread is allowed to operate a Vector Object and hence it is Thread-Safe.
  • Relatively performance is high because Threads are not required to wait to operate on an ArrayList Object. Relatively performance is low because Threads are required to wait to operate on a Vector Object.
  • ArrayList is introduced in 1.2 version and it is non-legacy. Vector is introduced in 1.0 version and it is legacy.

How to get Synchronized Version of ArrayList Object

  • By default ArrayList is non-synchronized but we can synchronized version of ArrayList Object by using the following method of Collections class to attain Thread-Safe features.
public static <T> List<T> synchronizedList(List<T> list) {
return (list instanceof RandomAccess ?
new SynchronizedRandomAccessList<>(list) :
new SynchronizedList<>(list));
}
 /* Here the below arrayList object is non-synchronized and is not Thread-Safe */
ArrayList arrayList = new ArrayList<>();
/* To attain Synchronized and Thread-Safe feature we are using the below code */
List list = Collections.synchronizedList(arrayList);
  • Similarly we can get Synchronized version of Map and Set Objects by using the following methods of Collections.
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<>(m);
}
public static <T> Set<T> synchronizedSet(Set<T> s) {
return new SynchronizedSet<>(s);
}

LinkedList


Set(I)

  • It is the Child interface of Collection.
  • If we want to represent a group of individual Objects as a single entity where duplicates are not allowed and insertion order is not required then we should go for Set Interface.

SortedSet (I)

  • It is the Child interface of Set.
  • If we want to represent a group of individual objects as single entity where duplicates are not allowed and all the objects should be inserted according to some sorting order then we should go for SortedSet Interface.

NavigableSet(I)

  • It is the Child interface of SortedSet.
  • It contains several methods for navigation purposes.

Differences between List and Set

  • Duplicates are allowed in a List and in a Set, duplicates are not allowed.
  • Insertion order is preserved in a List and in a Set, insertion order is not preserved.

Queue (I)

  • It is the Child interface of Collection.
  • If we want to represent a group of individual objects, prior to processing then we should go for Queue.
  • Usually Queue follows First-In-First-Out (FIFO) but based on our requirement but we can implement our own priority order also e.g.
    • Before sending a mail all mail id's, we have to store in some data structure. In which order we added mail ids, in the same order only mail should be delivered. For this requirement Queue is best choice.

Map(I)

  • Map is not a Child interface of Collection.
  • If we want to represent a group of objects as key-value pairs then we should go for Map.
  • Both key and value are objects only.
  • Duplicate keys are not allowed but values can be duplicated.
  • Map Interfaces and Classes in details

SortedMap(I)

  • It is the Child interface of Map.
  • If we want to represent a group of key-value pairs according to some sorting order of keys then we should go for SortedMap.
  • In SorteMap, the sorting should be based on key but not to be based on value.

NavigableMap (I)

  • It is the Child interface of SortedMap.
  • It defines several methods for navigation purposes.
The following are Legacy Characters present in Collection Framework
  • Enumeration (I - Interface)
  • Dictionary (AC - Abstract Class)
  • Vector (C - Class)
  • Stack (C - Class)
  • Hashtable (C - Class)
  • Properties (C - Class)

Do's and Dont's

  • All the above interfaces (Collection, List, Set, SortedSet, NavigableSet and Queue) meant for representing a group of individual objects.
  • If we want to represent a group of objects as key-value pairs then we should go for Map.

Reference



Comments

Popular posts from this blog

OOPS Concept in Java