Java – ArrayList Internal Implementation

Internally ArrayList in Java uses array to store its element. It’s an Object array which is defined as follows.

transient Object[] elementData;

1. Very First step : Declaration of ArrayList

When we declare an arraylist, we define a constructor, hence defining a capacity for the arraylist.

If we create Arraylist using Default constructor, then the capacity will be calculated in a way like this, see the code below:

      
public ArrayList() {
  this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

where DEFAULTCAPACITY_EMPTY_ELEMENTDATA is defined as an empty array, like this, see the code below:

      
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 
      
private static final int DEFAULT_CAPACITY = 10;

If we create Arraylist constructor by passing the capacity, then the capacity will be calculated in a way like this, see the code below:

        
public ArrayList(int initialCapacity) {
  if (initialCapacity > 0) {
      this.elementData = new Object[initialCapacity];
  } else if (initialCapacity == 0) {
      this.elementData = EMPTY_ELEMENTDATA;
  } else {
      throw new IllegalArgumentException("Illegal Capacity: "+
                                        initialCapacity);
  }
}

See in the code above, the condition if(initialCapacity>0) then it will create an array elementData of size of that very capacity which was passed.

If we create ArrayList from another collection, then elements of passed collection are copied to elementData array.

        
elementData = c.toArray();

see the code below:

        
public ArrayList(Collection<? extends E> c) {
  elementData = c.toArray();
  if ((size = elementData.length) != 0) {
      if (elementData.getClass() != Object[].class)
          elementData = Arrays.copyOf(elementData, size, Object[].class);
  } else {
      // replace with empty array.
      this.elementData = EMPTY_ELEMENTDATA;
  }
}

If you see in this code above, you will notice that the elementData array(or passed collection) is converted to an array of type Object.

2. add() : What happens next when you add an element ?

The below code gets called.

        
public boolean add(E e) {
  ensureCapacityInternal(size + 1);  // Increments modCount!!
  elementData[size++] = e;
  return true;
}

which at first ensures the capacity of the arraylist, then adds the elements to the end of the list. If the capacity is exhausted a new array is created with 50% more capacity than the previous one. All the elements are also copied from previous array to new array.

        
private void ensureCapacityInternal(int minCapacity) {
  if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
      minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
  }

  ensureExplicitCapacity(minCapacity);
}  

As you can see it’s here that the capacity is actually initialized as 10, if required to set to default.

          
private void ensureExplicitCapacity(int minCapacity) {
  modCount++;

  // overflow-conscious code
  if (minCapacity - elementData.length > 0)
      grow(minCapacity);
} 
  

From this code, if required, grow() method is called to increase the capacity of the ArrayList.

      
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
  private void grow(int minCapacity) {
      // overflow-conscious code
      int oldCapacity = elementData.length;
      int newCapacity = oldCapacity + (oldCapacity >> 1);
      if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0)
          newCapacity = hugeCapacity(minCapacity);
      // minCapacity is usually close to size, so this is a win:
      elementData = Arrays.copyOf(elementData, newCapacity);
  }

As you can see right shift operator is used to increase the capacity by 50% in the following statement. int newCapacity = oldCapacity + (oldCapacity >> 1);

Also the elementData array is changed to have the new capacity, elements from the old array are also copied to the new array. elementData = Arrays.copyOf(elementData, newCapacity);

So that’s how internally ArrayList keeps on growing dynamically.

3. remove() : What happens when you remove an element ?

If you remove any element from an array then all the subsequent elements are to be shifted to fill the gap created by the removed element.

See the code below:

        
/**
* Removes the element at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from their
* indices).
*/
public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                        numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}   

So that is how an arraylist grows and reduces in size dynamically.

So here we are, we hope now you are confident and know how to use ArrayList in java.

We tried our best to simplify the explanation, if you feel any difference or you need help in understanding any such thing, then feel free to contact us through email and subscribe to ProgrammerToday.


Java – ArrayList

It is a resizable array or a dynamic array. It uses this dynamic array mechanism to store its elements. ArrayList class is found in the java.util package in java.

Hierarchy of ArrayList class

            
public class ArrayList<E> extends AbstractList<E> implements List<E>, 
                                  RandomAccess, Cloneable, Serializable  
            

Features of ArrayList

  • An ArrayList allows duplicate elements.
  • An ArrayList maintains the insertion order.
  • An ArrayList is not synchronized, hence not thread safe.
  • An ArrayList allows RandomAccess of elements as it implements the same interface functionality.
  • Insertion/deletion operation is a little slow if compared to a linkedList as arrayList does a lot of shifting of elements(being a resizable array).
  • The iterators returned by iterator and listIterator methods of ArrayList are fail-fast. Which means, if the list is structurally modified at any time after the iterator is created, in any way except through the iterator’s own remove or add methods, the iterator will throw a ConcurrentModificationException.

ArrayList Constructors

  1. ArrayList() : This is used to build an empty arrayList.
  2. ArrayList(int capacity) : This is used to build an array list that has the specified initial capacity.
  3. ArrayList(Collection <? extends E> c) : This is used to build an array list that is initialized with the elements of the collection c .

Coding Examples of HashMap


1. Declare & Add Items to ArrayList

import java.util.ArrayList; // import this class

public class TestArrayList { 
  public static void main(String[] args) { 
    ArrayList<String> vehicles = new ArrayList<String>();
    vehicles.add("Merc");
    vehicles.add("BMW");
    vehicles.add("Ford");
    vehicles.add("JLR");
    System.out.println(vehicles);
  } 
}

OUTPUT

[Merc, BMW, Ford, JLR]

2. Iterating Collection through the for-each loop

import java.util.*; 

class TraverseList{  
 public static void main(String args[]){  
  ArrayList<String> al=new ArrayList<String>();  
  al.add("Alpha");  
  al.add("Beta");  
  al.add("Gamma");  

  //Traversing list using for-each loop  
  for(String obj:al)  
    System.out.println(obj);  
  }  

 System.out.println("-------------");

 // Traversing list using java 8 forEach loop and lambda
  al.forEach(x -> {    // "x" can be replaced by any variable name
    System.out.println(x);
  });
}  

OUTPUT

Alpha
Beta
Gamma
-------------
Alpha
Beta
Gamma

3. set(), get(), isEmpty(), remove() methods of ArrayList

public static void main(String[] args) {
  
      List<String> groceryList = new ArrayList<String>();

       // Check if an ArrayList is empty
       System.out.println("Is the groceryList empty? : " + groceryList.isEmpty());

       groceryList.add("Deo");
       groceryList.add("Cookies");
       groceryList.add("Cereals");
       groceryList.add("Bread");
       groceryList.add("Cheese");

       // Find the size of an ArrayList
       System.out.println("Here is the grocery list of " + groceryList.size() +" items");
       System.out.println(groceryList);

       // Retrieve the element at a given index
       String perfume = groceryList.get(0);
       String lastItem = groceryList.get(groceryList.size() - 1);

       System.out.println("Best perfume: " + perfume);
       System.out.println("Last item in the list: " + lastItem);

       // Modify the element at a given index
       groceryList.set(4, "Amazon");
       System.out.println("Modified grocery list: " + groceryList);
       
       //remove the item from the list
       groceryList.remove(3);
       System.out.println("Grocery list after removing item 3: "+groceryList);
}

OUTPUT

Is the groceryList empty? : true
Here is the grocery list of 5 items
[Deo, Cookies, Cereals, Bread, Cheese]
Best perfume: Deo
Last item in the list: Cheese
Modified grocery list: [Deo, Cookies, Cereals, Bread, Amazon]
Grocery list after removing item 3: [Deo, Cookies, Cereals, Amazon]

4. ArrayList of User defined objects

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

class Employee {
    private String name;
    private int empId;

    public Employee(String name, int empId) {
        this.name = name;
        this.empId = empId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }
}

public class TestArraylist {
    public static void main(String[] args) {
        List<Employee> empList = new ArrayList<>();
        empList.add(new Employee("Jason", 30));
        empList.add(new Employee("Winston", 34));
        empList.add(new Employee("Bourne", 29));

        empList.forEach(Employee -> {
          System.out.println("Name : " + Employee.getName() + 
                             ", Employee Id : " + Employee.getEmpId());
        });
    }
}

OUTPUT

Name : Jason, Employee Id : 30
Name : Winston, Employee Id : 34
Name : Bourne, Employee Id : 29

Summary

So here we are, we hope now you are confident and know how to use ArrayList in java.

We tried our best to simplify the explanation, if you feel any difference or you need help in understanding any such thing, then feel free to contact us through email and subscribe to ProgrammerToday.


Java Collection Framework

Collection is a group of seperate objects represented as a single unit and collection framework is an architecture for representing and manipulating the collections.

Collection framework defines several interfaces,d Few of them are :

  • Collection Interface
  • List Interface
  • Set Interface
  • Queue Interface

Map Interface(though not exactly part of framework)

Few of the methods declared in the collection interface and overriden by the child classes

S.NoMethodUsage
1public boolean add(E e), addAll(Collection<? extends E> c)It is used to insert an element in this collection, the other is used to Insert one collection into another.
2public boolean remove(Object element), removeAll(Collection<?> c)used to delete an element, other is used to delete all elements of the collection
3public int size()returns total number of elements in the collection
4public boolean contains(Object element)used to search an element in the collection
5public int size()returns total number of elements in the collection
6public Iterator iterator()returns an iterator
7public boolean isEmpty()check collection for empty
8public int hashCode()returns hashcode of the collection

Iterable Interface

Few of the methods declared in the collection interface and overriden by the child classes

The Iterable interface is the root interface for all the collection classes. The Collection interface extends the Iterable interface and therefore all the subclasses of Collection interface also implement the Iterable interface.

It has only one abstract method:

 Iterator iterator() : 

and returns the iterator over the elements of type T.


Singleton Design Pattern | Implementation

Single Design Pattern is one of the creational style of design pattern. It is often used in scenarios where the class needs only one instance. One of the very common examples which we come across is the Database connection class, when we only need one connection to be shared among other Objects as creating multiple connections/separate connection for every other Object is a costly operation, which would slow down the operations.

How do you design a Singleton Class :

  • Make constructor as private
  • Write a static method which returns Object of same Singleton class. Here, the concept of Lazy initialization in used to write this static method.

How is Singleton Class different from Normal Class?

When instantiating a class, a normal class uses constructor where as a Singleton class will need a static method to create an instance of a class that too only if it is null i.e it is not already in use.

Different levels of making a class Singleton

Method 1: Classic Implementation also called lazy instantiation

class Singleton
{
    private static Singleton obj;
  
    // private constructor to force use of
    // getInstance() to create Singleton object
    private Singleton() {}
  
    public static Singleton getInstance()
    {
        if (obj==null)
            obj = new Singleton();
        return obj;
    }
}
            

Method 2: make getInstance() synchronized

// Thread Synchronized Java implementation of 
// singleton design pattern
class Singleton
{
    private static Singleton obj;
  
    private Singleton() {}
  
    // Only one thread can execute this at a time
    public static synchronized Singleton getInstance()
    {
        if (obj==null)
            obj = new Singleton();
        return obj;
    }
}
            

The main disadvantage of this is method is that using synchronized every time while creating the singleton object is expensive and may decrease the performance of your program

Method 3: Eager Instantiation

// Static initializer based Java implementation of
// singleton design pattern
class Singleton
{
    private static Singleton obj = new Singleton();
  
    private Singleton() {}
  
    public static Singleton getInstance()
    {
        return obj;
    }
}
            

Method 4 (Best): Use “Double Checked Locking”

// Double Checked Locking based Java implementation of
// singleton design pattern
class Singleton
{
    private volatile static Singleton obj;
  
    private Singleton() {}
  
    public static Singleton getInstance()
    {
        if (obj == null)
        {
            // To make thread safe
            synchronized (Singleton.class)
            {
                // check again as multiple threads
                // can reach above step
                if (obj==null)
                    obj = new Singleton();
            }
        }
        return obj;
    }
}              
            

Advantages of Singleton

Saves memory because object is not created at each request. Only single instance is reused again and again.

Summary

In this article we learnt about Singleton Design Pattern and its Implementation.
Hope you liked the article !


Java 8 – Optional

A new class Optional in java.util package used to represent a value is present or absent, its main purpose it to keep us away from too many null checks and NullPointerExceptions

Advantages of using Java 8 Optional :

  1. No more NullPointerException at run-time.
  2. Develop clean and neat APIs.
  3. No more Boiler plate code.
  4. Null checks are not required.

Various methods in Optional object

1. Code to retrieve the wrapped value using get API

Optional<String> opt = Optional.of("programmertoday");
String name = opt.get();

2. Basic Methods from Optional

Optional.ofNullable() method : returns a Non-empty Optional if a value present in the given object. Otherwise returns empty Optional.
Optional.empty() method : useful to create an empty Optional object.

import java.util.Optional;

public class OptionalBasicExample {
    public static void main(String[] args) {
        Optional<String> gender = Optional.of("MALE");
        String answer1 = "Yes";
        String answer2 = null;
        System.out.println("Non-Empty Optional:" + gender);
        System.out.println("Non-Empty Optional: Gender value : " + gender.get());
        System.out.println("Empty Optional: " + Optional.empty());
        System.out.println("ofNullable on Non-Empty Optional: " + Optional.ofNullable(answer1));
        System.out.println("ofNullable on Empty Optional: " + Optional.ofNullable(answer2));   // java.lang.NullPointerException   System.out.println("ofNullable on Non-Empty Optional: " +    Optional.of(answer2));     
       
        } }
        Output:
        Non - Empty Optional:
        Optional[MALE]
        Non - Empty Optional:
        Gender value :MALE
        Empty Optional:Optional.empty

        ofNullable on Non - Empty Optional:
        Optional[Yes]
        ofNullable on Empty Optional:Optional.empty

        Exception in thread "main" java.lang.NullPointerExceptio
        at java.util.Objects.requireNonNull(Objects.java:203)
        at java.util.Optional.<init> (Optional.java:96)
        at java.util.Optional.of(Optional.java:108)

3. Optional – map and flatMap methods

Optional.ofNullable() method returns a Non-empty Optional if a value present in the given object. Otherwise returns empty Optional.
Optionaal.empty() method is useful to create an empty Optional object.

import java.util.Optional;

public class OptionalMapFlatMapExample {
    public static void main(String[] args) {
        Optional<String> nonEmptyGender = Optional.of("male");
        Optional<String> emptyGender = Optional.empty();
        System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase));
        System.out.println("Empty Optional    :: " + emptyGender.map(String::toUpperCase));
        Optional<Optional<String>> nonEmptyOtionalGender = Optional.of(Optional.of("male"));
        System.out.println("Optional value   :: " + nonEmptyOtionalGender);
        System.out.println("Optional.map     :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase)));
        System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));
    }
}

Output:
        Non-Empty Optional::Optional[MALE]
        Empty Optional::Optional.empty
        Optional value::Optional[Optional[male]]
        Optional.map::Optional[Optional[MALE]]
        Optional.flatMap::Optional[MALE]

4. Optional – filter method

import java.util.Optional;

public class OptionalFilterExample {
    public static void main(String[] args) {
        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty(); //Filter on Optional   
        System.out.println(gender.filter(g -> g.equals("male"))); //Optional.empty   
        System.out.println(gender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional[MALE]   
        System.out.println(emptyGender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional.empty   
        } 
}
        
Output:
        Optional.empty
        Optional[MALE]
        Optional.empty

5. Optional – isPresent and ifPresent methods

Optional.isPresent() returns true if the given Optional object is non-empty. Otherwise it returns false.
Optional.ifPresent() performs given action if the given Optional object is non-empty. Otherwise it returns false

import java.util.Optional;

public class OptionalIfPresentExample {
    public static void main(String[] args) {
        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();
        if (gender.isPresent()) {
            System.out.println("Value available.");
        } else {
            System.out.println("Value not available.");
        }
        gender.ifPresent(g -> System.out.println("In gender Option, value available."));   //condition failed, no output print   
        emptyGender.ifPresent(g -> System.out.println("In emptyGender Option, value available."));
    }
}

Output:
        Value available.
        In gender Option,value available.

6. Optional – orElse and orElseGet methods

It returns the value if present in Optional Container. Otherwise returns given default value.

import java.util.Optional;

public class OptionalOrElseExample {
    public static void main(String[] args) {
        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();
        System.out.println(gender.orElse("<N/A>")); //MALE   
        System.out.println(emptyGender.orElse("<N/A>")); //<N/A>   
        System.out.println(gender.orElseGet(() -> "<N/A>")); //MALE   
        System.out.println(emptyGender.orElseGet(() -> "<N/A>")); //<N/A>   
    }
}

Output:
        MALE
        <N/A>
        MALE
        <N /A>

Summary

In this article we learnt about Java 8 Optional package, its advantages and its variuos methods and implementations.
Hope you liked the article !


Java 8 – Lambdas

Lambda expressions or functions are nameless functions i.e just as anonymous function with no name.

Java earlier being only OOP language there was no existense of functions outside the object or instance. But since java 8 functional programming was introduced you can define functions, give them reference variables or pass them as method arguments and more.

Lambda syntax :

(x,y) -> x+y
1. (parameters) -> expression
2. (parameters) -> {statements;}
3. () -> expression

Some features of Lambda Expressions :

  1. A lambda expression can have zero, one or more parameters.
  2. When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses. e.g. a -> return a*a.
  3. The body of the lambda expressions can contain zero, one or more statements. If body of lambda expression has single statement curly brackets are not mandatory and the return type of the anonymous function is the same as that of the body expression. When there is more than one statement in body than these must be enclosed in curly brackets.

Lambda relationship with Functional interfaces

SAM-Single Abstract Method Inferfaces also called as functional interfaces, java 8 enforces the rule of SAM by annotating these interfaces with a new annotation i.e @FunctionalInferface

        
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}        
      

If you try to add a new method in any functional interface, compiler would not allow you to do this and will throw compile time error.

So, How are they related ?

Let us see an example to find the relation, there is a thread which prints “Test Functional Interface”

        
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Test Functional Interface");
    }
}).start();
        
      

When we use lambda here , above code equivalent lambda is like this :

        
new Thread(
    () ->   {
                System.out.println("My Runnable run method");
            }
  ).start();
        
      

In simple words, a lambda expression is an instance of a functional interface.

Examples : Java 8 lambda expression

1. Iterating over a List and perform some operations

        
List<String> list = new ArrayList();
list.add("1");
list.add("2");
  
list.forEach(p ->  {
                    System.out.println(p);
                    //Do more work
                    }
                  );
        
      

2. Create a new runnable and pass it to thread

        
new Thread(
    () -> System.out.println("My Runnable");
).start();  
        
      

3. Sorting employees objects by their name

        
public class LambdaIntroduction {

public static void main (String[] ar){
  Employee[] employees  = {
      new Employee("David"),
      new Employee("Naveen"),
      new Employee("Alex"),
      new Employee("Richard")};
    
  System.out.println("Before Sorting Names: "+Arrays.toString(employees));
  Arrays.sort(employees, Employee::nameCompare);
  System.out.println("After Sorting Names "+Arrays.toString(employees));
        }
  }

class Employee {
  String name;
  
  Employee(String name) {
    this.name = name;
  }
  
  public static int nameCompare(Employee a1, Employee a2) {
    return a1.name.compareTo(a2.name);
  }
    
  public String toString() {
    return name;
  }
}
  
Output:
  
Before Sorting Names: [David, Naveen, Alex, Richard]
After Sorting Names [Alex, David, Naveen, Richard]  
        
      

Summary

In this article we learnt about Java 8 lambda expression, we learnt its syntax, its features, lambda with functional interface and its various other implementations with examples, try it out.
Hope you liked the article !


Java 8 – Functional Programming

Functional programming contains the following key concepts:

  • Functions as first class objects
  • Pure functions
  • Higher order functions

Pure functional programming has a set of rules to follow too:

  • No state
  • No side effects
  • Immutable variables
  • Favour recursion over looping

All the rules may not be applied at all times but you can still benefit by functional programming

Higher Order Functions

A function is a higher order function if at least one of the following conditions are met:
1. The function takes one or more functions as parameters.
2. The function returns another function as result.

      
public class HigherOrderFunctionClass {

  public <T> TestFactory<T> createTestFactory
    (IProducer<T> prod, IConfigurator<T> config) {
      
      return () -> {
          T obj = prod.produce();
          config.configure(obj);
          return obj;
      }
    }
  }
      >
    

Functional Interfaces

A functional interface in Java is an interface that only has one abstract method. By an abstract method is meant only one method which is not implemented. An interface can have multiple methods, e.g. default methods and static methods, both with implementations, but as long as the interface only has one method that is not implemented, the interface is considered a functional interface.

Example of a functional interface:

      
public interface MyInterface {
    public void run();
}
      
      

Here is another example of a functional interface with a default method and a static method too:

      
public interface MyInterface2 {
    public void run();

    public default void doIt() {
        System.out.println("doing it");
    }

    public static void doItStatically() {
        System.out.println("doing it statically");
    }
}
        
      

Notice the two methods with implementations. This is still a functional interface, because only run() is not implemented (abstract). However, if there were more methods without implementation, the interface would no longer be a functional interface, and could thus not be implemented by a Java lambda expression.

Summary

In this article we learnt about the Java 8 Functional Programming, Higher Order functions, functional interfaces and its examples.
Hope you liked the article !


Linkedlist

It is a linear data structure, unlike arrays it is not stored at contiguous location, the elements called nodes are linked using pointers, each pointer pointing to the next node.

Each node consists of mainly two part:

  • Data
  • Reference Link or address of next node and previous node

In java internally linkedlist is implemented using doubly linked list, in which we can add & remove elements from both sides of the list.

Features of LinkedList

  • Java LinkedList is an implementation of the List and Deque interfaces. It extends AbstractSequentialList and implements List and Deque interfaces.
  • It maintains the insertion order of the elements and also allow null elements.
  • In Java applications, we can use it as a List, stack or queue.
  • It does not support random access as it doesn’t implement RandomAccess Interface, so you cannot access elements randomly you have to access it sequentially(whereas Stack & ArrayList do implement this interface).
  • You can use ListIterator/Iterator to iterate LinkedList elements.

Different Ways to iterate over LinkedList

      
import java.util.LinkedList;
import java.util.Iterator;
public class ProgrammerTodayLinkedListExample{

  public static void main(String[] args) {

   LinkedList<String> list = new LinkedList<String>();
   list.add("welcome");
   list.add("to");
   list.add("LinkedList");
      
   System.out.println("*****Iterate Using Iterator*****");
   for (Iterator i = list.iterator(); i.hasNext();) {
     System.out.println(i.next());
   }
   
   System.out.println("*****Iterate Using ListIterator*****");
   ListIterator<String> listIterator = linkedList.listIterator();
   while (listIterator.hasNext()) {
     System.out.println(listIterator.next());
   }
   
   System.out.println("*****Iterate Using Traditional for loop*****");
   for (int i = 0; i < list .size(); i++) {
     System.out.println(list .get(i));
   }
    
   System.out.println("*****Iterate using Java8 forEach loop*****");
   // forEach Performs the given action for each element of the Iterable until 
   // all elements have been processed or the action throws an exception.
   linkedList.forEach(System.out::println); 
  }
}

OUTPUT

    
*****Iterate Using Iterator*****
welcome
to
LinkedList
*****Iterate Using ListIterator*****
welcome
to
LinkedList
*****Iterate Using Traditional for loop*****
welcome
to
LinkedList
*****Iterate using Java8 forEach loop*****
welcome
to
LinkedList    
    

LinkedList as Deque

Observe below in code block that on the left is the Deque Interface reference which creates a LinkedList object on the right. By this way linkedList can inherit Deque methods like addFirst(), addLast(), removeFirst(), removeLast(), etc methods.

    
import java.util.LinkedList;
import java.util.Deque;

public class LinkedListDequeExample 
{
  public static void main(String[] args) 
  {
  Deque<String> listDeque= new LinkedList<String>();
  listDeque.add(2);
  listDeque.addFirst(1);
  listDeque.addLast(3);
  listDeque.addFirst(0);
  listDeque.addLast(4);
      
  System.out.println("LinkedList contents : " + listDeque);
  System.out.println("LinkedList size : " + listDeque.size());
  listDeque.removeFirst();
  listDeque.removeLast();
  
  System.out.println("LinkedList contents : " + listDeque);
  System.out.println("LinkedList size : " + listDeque.size());	
  }
}

OUTPUT

      
  LinkedList contents : [0, 1, 2, 3, 4]
  LinkedList size : 5
  LinkedList contents : [1, 2, 3]
  LinkedList size : 3
  

LinkedList to Streams in Java 8

In java 8 use streams with forEach loop to iterate over the linkedlist.

    
List<Integer> ptlist= new LinkedList<>();
ptlist.add(11);
ptlist.add(22);
ptlist.add(33);
  
//Using stream to iterate through the List
ptlist.stream().forEach(System.out::println);
  

OUTPUT

    
11
22
33 
  

Difference between ArrayList and LinkedList | Usage

S.NoArrayListLinkedList
1Insertions & deletions are slowerInsertions & deletions are easy and fast in LinkedList because there is no resizing like arrays and then copying to another array if it gets full.
2Memory overhead is less as compared to LL as it stores only the dataMemory overhead is more as it stores both address and data
3Accessing an element in an array is fastwhile Linked list takes linear time(i.e have to start from the head), so it is quite a bit slower
4Arrays are of fixed sizeLinked lists are dynamic and flexible and can expand and contract its size
5In an array, memory is assigned during compile timewhile in a Linked list it is allocated during execution or runtime
4Arrays are of fixed sizeLinked lists are dynamic and flexible and can expand and contract its size

Example : Reverse a LinkedList without creating another one(without using additional space)

Algorithm:

  1. Create a linked list with n elements.
  2. Run the loop for n/2 times where ‘n’ is the number of elements in the linkedlist.
  3. In the first pass, Swap the first and nth element.
  4. In the second pass, Swap the second and (n-1)th element and so on till you reach the mid of the linked list.
  5. Return the linked list after loop termination.
      
import java.util.*; 

public class LinkedListTest2 { 
public static void main(String[] args) 
{ 
    // Declaring linkedlist without any initial size 
    LinkedList<Integer> linkedli = new LinkedList<Integer>(); 

    // Appending elements at the end of the list 
    linkedli.add(new Integer(1)); 
    linkedli.add(new Integer(2)); 
    linkedli.add(new Integer(3)); 
    linkedli.add(new Integer(4)); 
    linkedli.add(new Integer(5)); 
    System.out.print("Elements before reversing: " + linkedli); 

    // Calling user defined function for reversing 
    linkedli = reverseLinkedList(linkedli); // or use Collections.reverse(linkedli); 
    System.out.print("\nElements after reversing: " + linkedli); 
} 

// Takes a linkedlist as a parameter and returns a reversed linkedlist 
public static LinkedList<Integer> reverseLinkedList(LinkedList<Integer> llist) 
{ 
    for (int i = 0; i < llist.size() / 2; i++) { 
        Integer temp = llist.get(i); 
        llist.set(i, llist.get(llist.size() - i - 1)); 
        llist.set(llist.size() - i - 1, temp); 
    } 

    // Return the reversed arraylist 
    return llist; 
} 
} 

Time Complexity: O(n/2)
Space Complexity: O(1)

Output:

Elements before reversing: [1, 2, 3, 4, 5]
Elements after reversing: [5, 4, 3, 2, 1]

Good To Know – Internal working of LinkedList

Click “Internals of LinkedList” to Read More …