Thursday, 29 June 2017

Java collection Framework

The Java Collections Framework is a collection of interfaces and classes which helps in storing and processing the data efficiently. This framework has several useful classes which have tons of useful functions which makes a programmer task super easy.



Let's explore one by one.


List:

A List is an ordered Collection (sometimes called a sequence). Lists may contain duplicate elements. It allows to have 1 or more null values. Elements can be inserted or accessed by their position in the list, using a zero-based index.
  • ArrayList
  • LinkedList
  • Vector

ArrayList:

ArrayList is a resizable-array implementation of the List interface. It implements all optional list operations, and permits all elements, including null.

Array lists are created with an initial size. When this size is exceeded, the collection is automatically enlarged. When objects are removed, the array may be shrunk.



Click here to know more about the ArrayList and it's methods and the use of each method..

LinkedList:

Java LinkedList class uses doubly linked list to store the elements. It provides a linked-list data structure. It inherits the AbstractList class and implements List and Deque interfaces.
Click here to know more about the ArrayList and it's methods and the use of each method..
Difference Between LinkedList and ArrayList:


Set Collection:

Set is a type of collection that does not allow duplicate elements. That means an element can only exist once in a Set. Only one null value allowed in Set. 
Set is an Interface which extends Collections interface. 


Follow post HashSet, Treeset & LinkedHashSet to know more about the Set collection and it's implementations and the use of each of it's methods..

Map Collection:

A Map is an object that maps keys to values, or is a collection of Key-Value pairs.
Image result for java map key value pair

To know more about Map Collection follow post Map Collection.

HashSet, TreeSet & LinkedHashSet

Set Collection:

Set is a type of collection that does not allow duplicate elements. That means an element can only exist once in a Set. Only one null value allowed in Set. Set is an Interface which extends Collections interface. 
Based on the characteristics, consider using a Set collection when:

  • You want to store elements distinctly without duplication, or unique elements.
  • You don’t care about the order of elements.
For example, you can use a Set to store unique integer numbers; For instance storing the student Ids which are unique etc. If you think there will be a chance of having duplicate values the Set is not your choice, chose List for this case.

There are three classes which implements Set interface. Let’s look at each implementation in details:
  • HashSet: is the best-performing implementation and is a widely-used Set implementation. It represents the core characteristics of sets: no duplication and unordered.
  • LinkedHashSet: This implementation orders its elements based on insertion order. So consider using a LinkedHashSet when you want to store unique elements in order.
  • TreeSet: This implementation orders its elements based on their values, either by their natural ordering, or by a Comparator provided at creation time.
Therefore, besides the uniqueness of elements that a Set guarantees, consider using HashSet when ordering does not matter; using LinkedHashSet when you want to order elements by their insertion order; using TreeSet when you want to order elements by their values.

Difference between HashSet, LinkedHashSet and TreeSet:





Let's explore above three Set implementation classes.

Creating a HashSet, LinkedHashSet or TreeSet in java:


Set<String> hashSet = new HashSet<>();
Set<String> linkedHashSet = new LinkedHashSet<>();
Set<String> treeSet = new TreeSet<>();

Creating HashSet, LinkedHashSet or TreeSet as easy as creating any variable in Java. But if you observe carefully we are assign all the Set classes to Set which is an Interface where HashSet, LinkedHashSet or TreeSet implements it. To know more about this please follow post Programming to Interfaces.

Apart from initialization or creating the different Sets, using all of it's methods are same. Means all HashSet, LinkedHashSet or TreeSet classes have very important methods in common as all of them implement same Interface called Set. So we use HashSet in all examples in this post to explore all the important methods.

Add Method:

Add an element to the Set.

Example:

import java.util.HashSet;
import java.util.Set;

public class SetDemo {

  public static void main(final String[] args) {
    // Create an HashSet and add two strings.
    final Set<String> set = new HashSet<>();
    set.add("Audi");
    set.add("BMW");
    System.out.println(set);
  }
}

Output:

[Audi, BMW]

addAll Method:
Appends all of the elements in the specified collection to the existing Set. Throws NullPointerException, if the specified collection is null.


import java.util.HashSet;
import java.util.Set;

public class SetDemo {

  public static void main(final String[] args) {
    final Set<String> set = new HashSet<>();
    set.add("Audi");
    set.add("BMW");
    set.add("Benz");
    System.out.println("Original Set: " + set);

    final Set<String> duplicate = new HashSet<>();
    //create a duplicate set from existing set
    duplicate.addAll(set);
    System.out.println("Duplicate Set: " + duplicate);
  }
}

Output:
Original Set: [Benz, Audi, BMW]
Duplicate Set: [Benz, Audi, BMW]

Get Method:
Because sets have no ordering. Some implementations do (particularly those implementing the java.util.SortedSet interface), but that is not a general property of sets.

If you're trying to use sets this way, you should consider using a list instead. So techincally there is no get method in Set.



size Method:

Returns the number of elements in this Set.


import java.util.HashSet;
import java.util.Set;
public class SetDemo { public static void main(final String[] args) { final Set<String> set = new HashSet<>(); set.add("Audi"); set.add("BMW"); set.add("Benz"); // print size of set System.out.println("Size of Set: " + set.size()); } } Output: Size of Set: 3


contains Method:

Searches whther a given element is present in the existing Set.
import java.util.HashSet;
import java.util.Set;
public class SetDemo { public static void main(final String[] args) { final Set<String> set = new HashSet<>(); set.add("Audi"); set.add("BMW"); set.add("Benz"); // Check set contains Audi System.out.println("Is set contain Audi: " + set.contains("Audi")); } } Output: Is set contain Audi: true


clear Method:

Removes all of the elements from the set. i.e. resets the set and size to 0.


isEmpty Method:

Check whether a set is empty means no elements in it. Returns true if empty or else false.

Let's use both clear and isEmpty methods in below example:

import java.util.HashSet;
import java.util.Set;
public class SetDemo { public static void main(final String[] args) { final Set<String> set = new HashSet<>(); set.add("Audi"); set.add("BMW"); set.add("Benz"); // print the current size of the Set System.out.println("The size of the LinkedList: " + set.size()); // Reset the Set using clear method set.clear(); System.out.println("Is Set empty: " + set.isEmpty()); } } Output: The size of the LinkedList: 3 Is Set empty: true


remove Method:

Removes the specific element in the Set. 


Note: removal will only possible with actual element value but not with index. Because sets have no ordering. Some implementations do (particularly those implementing the java.util.SortedSet interface), but that is not a general property of sets.


import java.util.HashSet;
import java.util.Set;
public class SetDemo { public static void main(final String[] args) { final Set<String> set = new HashSet<>(); set.add("Audi"); set.add("BMW"); set.add("Benz"); System.out.println("Original Set Elements" + set); // Removing BMW set.remove("BMW"); System.out.println("Set after removing BMW: " + set); } } Output: Original Set Elements[Audi, BMW, Benz] Set after removing BMW: [Audi, Benz]



toArray Method:

Returns an array containing all of the elements. Throws NullPointerException if the specified array is null.



import java.util.HashSet;
import java.util.Set;
public class SetDemo { public static void main(final String[] args) { final Set<String> set = new HashSet<>(); set.add("Audi"); set.add("BMW"); set.add("Benz"); Object[] array = set.toArray(); } }

Set as a Method Arguement: 

A Set can be passed as an argument to another method like in below example.


import java.util.HashSet;
import java.util.Set;

public class SetDemo {

  public static void printSet(final Set<String> set) {
    for (final String item : set) {
      System.out.println(item);
    }
  }

  public static void main(final String[] args) {
    final Set<String> set = new HashSet<>();
    set.add("Audi");
    set.add("BMW");
    set.add("Benz");

    printSet(set);
  }
}

Output:
Benz
Audi
BMW

Here:I have a method to print Set values that receives any Set implemented class variable as an argument. This method does not create new objects. So, this method can be reused whenever you want to print the values of a Set. Thus you are reducing the redundant code.





Programming to Interfaces


Most of the time we create LinkedList or ArrayList like below,

LinkedList<String> list = new LinkedList<>();
ArrayList<String> list = new ArrayList<>();

This is fine when we are at the learning phase. But in real time it's better to follow best practices of Java coding which enable robustness and efficiency of the code. If we have to follow best practices then the above line will change to, 


List<String> list = new LinkedList<>();
List<String> list = new ArrayList<>();

Let's see why:

According to LinkedList and ArrayList implementation, both inherits the AbstractList class and implements List. In Java there is a saying which highlights one of the best practices.

"programming to interface, not implementation"

Means the second has the advantage that the implementation of the List can change (to a LinkedList for example), without affecting the rest of the code. This is difficult to do with an ArrayList, not only because you will need to change ArrayList to LinkedList everywhere, but also because you may have used ArrayList specific methods.

Let's try to understand above situation with an example, in this example we program to implementation means we create LinkedList variable with LinkedList class itself but not to it's Interface called List.



import java.util.LinkedList;

public class LinkedListDemo {

  public static void printLinkedList(final LinkedList<String> linkedList) {
    for (final String item : linkedList) {
      System.out.println(item);
    }
  }

  public static void main(final String[] args) {
    final LinkedList<String> list = new LinkedList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");

    printLinkedList(list);
  }
}

Output:
Audi
BMW
Benz

All of sudden I want to change from LinkedList to ArrayList due to some design change in the application. Let's see, in how many places we have to make the code changes.


import java.util.ArrayList;

public class ArrayListDemo {

  //Change here
  public static void printArrayList(final ArrayList<String> arrayList) {
    for (final String item : arrayList) {
      System.out.println(item);
    }
  }

  public static void main(final String[] args) {
    //change here
    final ArrayList<String> list = new ArrayList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");

    printArrayList(list);
  }
}

Output:
Audi
BMW
Benz

In a small example we changed the code in couple of places. Assume in a large applications where thousand to million lines of code exists, it's very hard to change.

Let's consider the second way where program to an interface means creating your variable with List interface. Let's first create an ArrayList which is assigned to a List interface.



import java.util.ArrayList;
import java.util.List;

public class ArrayListDemo {

  public static void printList(final List<String> list) {
    for (final String item : list) {
      System.out.println(item);
    }
  }

  public static void main(final String[] args) {
    final List<String> list = new ArrayList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");

    printList(list);
  }
}

Output:
Audi
BMW
Benz

Now let's make the changes in the code to use LinkeLlist,


import java.util.LinkedList;
import java.util.List;

public class LinkedListDemo {

  //no need to Change here. Remains same as above
  public static void printList(final List<String> list) {
    for (final String item : list) {
      System.out.println(item);
    }
  }

  public static void main(final String[] args) {
    //change here. This is only place you change 
    final List<String> list = new LinkedList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");

    printList(list);
  }
}

Output:
Audi
BMW
Benz

In above example when you decided to use LinkedList instead ArrayList, you are changing the code at one place where you create a list. This gives you a flexibility to change to any implementation class i.e ArrayList, LinkedList or any class that implements the List interface safely without affecting your code. So use Interfaces instead direct implementation class.

Not only in case of List, it also applicable in terms of any interface which has many implementation classes. For example,

  • Set is an Interface and it has HashSet, TreeSet and LinkedHashSet classes which implement Set.
  • Map is an Interface and it has HashMap, TreeMap and LinkedHashMap classes which implement Set. or
  • It can be customer created Interface and it's implementations.


Wednesday, 28 June 2017

LinkedList and It's Methods



LinkedList:

Java LinkedList class uses doubly linked list to store the elements. It provides a linked-list data structure.
The important points about Java LinkedList are:

  • Can contain duplicate elements.
  • Maintains insertion order.
  • Is non synchronized.
  • Manipulation is fast because no shifting needs to be occurred.

Doubly Linked List:



A doubly linked list whose nodes contain three fields: a value, the link to the next node, and the link to the previous node.In case of doubly linked list, we can add or remove elements from both side.

Following is the list of the constructors provided by the LinkedList class.


LinkedList( ) - Default constructor:

This constructor builds an empty LinkedList.

Consider following example where we create an empty LinkedList with it's default constructor.

import java.util.LinkedList;

public class LinkedListDemo {

  public static void main(final String[] args) {
    final LinkedList<Integer> elements = new LinkedList<>();
    System.out.println(elements.size());
  }
}

Output:
0

LinkedList(Collection c):

This constructor builds an linked list that is initialized with the elements of the collection c.

Consider you have a Set collection and you want to covert from Set to an LinkedList. This constructor comes handy for these operations, like, converting any other collection to LinkedList or creating a replica of existing LinkedList.

Example for converting as Set to a LinkedList:


import java.util.LinkedList;
import java.util.HashSet;
import java.util.Set;

public class LinkedListDemo {

  public static void main(final String[] args) {
    final Set<Integer> set = new HashSet<>();
    set.add(1);
    set.add(2);
    set.add(3);
    //Converting Set to linkedlist
    final LinkedList<Integer> linkedList = new LinkedList<>(set);
    System.out.println(linkedList);

    //Creating replica of existing LinkedList
    final LinkedList<Integer> linkedList2 = new LinkedList<>(linkedList);
    System.out.println(linkedList2);
  }
}

Output:
[1, 2, 3]
[1, 2, 3]


LinkedList(int capacity):

This constructor builds a linked list that has the specified initial capacity. The capacity is the size of the underlying array that is used to store the elements. The capacity grows automatically as elements are added to an linked list.

Suppose you already have an Array with the size 5 and you decided to convert Array to LinkedList. You can create Linkedlist with exactly the size of the Array which you want to convert.

import java.util.LinkedList;
import java.util.Arrays;

public class LinkedListDemo {

  public static void main(final String[] args) {
    final Integer[] intArray = {1, 2, 3, 4, 5};
    //Converting Array to LinkedList
    final LinkedList<Integer> linkedList = new LinkedList<>(5);
    System.out.println(linkedList.size);
  }
}

Output:
5

Note: Arrays.asList() converts any array to List which is from Arrays class. We will discuss more about Arrays class later in this tutorial.

Now you know how to create a LinkedList. LinkedList class has so many predefinaed methods which helps to finish out task super easy.  We will discuss some important methods.

Note: For Java best practices in creating a Linked List please follow post Programming to Interfaces.


Add Method:

There are 2 add methods available in LinkedList.

They are,

boolean add(Object o): appends an element to the end of an LinkedList.

void add(int index, Object element): Inserts the specified element at the specified position index in this list. When you insert an element at any index, then it shifts the following elements to make room. Throws IndexOutOfBoundsException if the specified index is out of range (index < 0 || index > size()).

Example below shows how to use effectively above add methods:

import java.util.LinkedList;

public class LinkedListDemo {

  public static void main(final String[] args) {
    // Create an LinkedList and add two strings.    
    final LinkedList<String> list = new LinkedList<>();
    list.add("Audi");
    list.add("BMW");
    System.out.println(list);

    // Add an extra element at index 0.
    // This will move all the existing following elements to make room.
    list.add(0, "Benz");
    System.out.println(list);
  }
}

Output:
[Audi, BMW]
[Benz, Audi, BMW]


addAll Method:
Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator. Throws NullPointerException, if the specified collection is null.



import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");
    System.out.println("Original LinkedList: " + list);    // Let's create a duplicate LinkedList of above using addAll method    final LinkedList<String> duplicate = new LinkedList<>();
    duplicate.addAll(list);
    System.out.println("Duplicate LinkedList: " + duplicate);  }
}

Ouput:
Original LinkedList: [Audi, BMW, Benz]
Duplicate LinkedList: [Audi, BMW, Benz]

set Method:
Replaces the element at the specified position with the specified element. Throws IndexOutOfBoundsException if the specified index is out of range (index < 0 || index >= size()).

import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); System.out.println("LinkedList before Set operation: " + list);
    //Replace 0th element which is Audi with Honda
    list.set(0, "Honda");
    System.out.println("LinkedList After Set operation: " + list);  }
}

Ouput:
LinkedList before Set operation: [Audi, BMW, Benz]
LinkedList After Set operation: [Honda, BMW, Benz]


Get Method:

Returns the element at the specified position in this list. Throws IndexOutOfBoundsException if the specified index is out of range (index < 0 || index >= size()).



import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); // Get 2nd element which is BMW. We have to use index 1 as list index starts from 0. System.out.println("2nd Element of the LinkedList: " + list.get(1)); } } Output: BMW



size Method:

Returns the number of elements in this list.



import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); // print the current size of the LinkedList System.out.println("The size of the LinkedList: " + list.size()); } }

Output:
The size of the LinkedList: 3

contains Method:

Searches whther a given element is present in the existing list.

import java.util.LinkedList;

public class LinkedListDemo {

  public static void main(final String[] args) {
    final LinkedList<String> list = new LinkedList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");

    System.out.println("Is list contains Audi: " + list.contains("Audi"));  
  }
}

Output:
The size of the LinkedList: 3
Is list contains Audi: true


clear Method:

Removes all of the elements from this list. i.e. resets the list and size to 0.


isEmpty Method:

Check whether a list is empty means no elements in it. Returns true if empty or else false.

Let's use both clear and isEmpty methods in below example:


import java.util.LinkedList;

public class LinkedListDemo {

  public static void main(final String[] args) {
    final LinkedList<String> list = new LinkedList<>();
    list.add("Audi");
    list.add("BMW");
    list.add("Benz");

    // print the current size of the LinkedList
    System.out.println("The size of the LinkedList: " + list.size());
    // Reset the list using clear method
    list.clear();
    System.out.println("Is LinkedList empty: " + list.isEmpty());  
  }
}

Output:
The size of the LinkedList: 3
Is LinkedList empty: true

remove Method:

Removes the element at the specified position in this list. Throws IndexOutOfBoundsException if the index out is of range (index < 0 || index >= size()).

import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); // print the current size of the LinkedList System.out.println("LinkedList before removing BMW which is 2nd element: " + list); // Removing BMW which is 2nd element. We have to use index 1 to for 2nd element as list index // starts from 0; list.remove(1); System.out.println("LinkedList after removing BMW which is 2nd element: " + list); } } Output: LinkedList before removing BMW which is 2nd element: [Audi, BMW, Benz] LinkedList after removing BMW which is 2nd element: [Audi, Benz]


indexOf Method:

Returns the index in of the first occurrence of the specified element, or -1 if the List does not contain this element.



import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); // print the current size of the LinkedList System.out.println("Printing index of BWM: " + list.indexOf("BMW")); } } Output: Printing index of BWM: 1


toArray Method:

Returns an array containing all of the elements in it's list in the correct order. Throws NullPointerException if the specified array is null.



import java.util.LinkedList;
public class LinkedListDemo { public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); // Converting LinkedList to an Array
    Object[] array = list.toArray();
  }
}

LinkedList as a Method Arguement: 

An LinkedList can be passed as an argument to another method like in below example.

import java.util.LinkedList;
public class LinkedListDemo { public static void printLinkedList(final LinkedList<String> linkedList) { for (final String item : linkedList) { System.out.println(item); } } public static void main(final String[] args) { final LinkedList<String> list = new LinkedList<>(); list.add("Audi"); list.add("BMW"); list.add("Benz"); printLinkedList(list); } } Output: Audi BMW Benz

Here:I have a method to print LinkedList values that receives an LinkedList as an argument. This method does not create new LinkedList objects. So, this method can be reused whenever you want to print the values of an LinkedList. Thus you are reducing the redundant code.