Open In App

How to Implement Stack in Java using LinkedList and Generics?

Last Updated : 21 May, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisites:

What is Stack?

Stack is a linear Data Structure that follows LIFO(Last In First Out) order while performing its operations. The main operations that are performed on the stack are mentioned below:

  • push() :  inserts an element at beginning of the stack(In singly linked list)
  • pop() : deletes first  element from of the stack(Topmost element)
  • peek() : returns the element which is at the beginning of the stack

Other than this operation there is another one called display(), which displays the contents of the stack. Now we are going to implement the Stack using a singly linked list and generics. If you are aware of the concept of generics, which allows us to use any data type as a type parameter, and the type of data is determined at the time of object creation. The advantages of using generics in classes, methods, and interfaces are, type-checking is done during object creation, code can be reused and the performance is better. 

Let’s see the implementation in the following example :

Java




// Java Program to Implement Stack Using LinkedList
// and Generics
// importing the required packages
import java.util.Scanner;
  
class LinkedStack<T> {
    // create a Node class
    private class Node {
  
        // A Node contains two parts inside it one is 'data'
        // part and the other is 'next' which has a
        // reference to the next Node
        T data;
        Node next;
  
        // define a parameterized constructor which
        // initializes the local variables of Node class
        public Node(T data, Node next)
        {
            this.data = data;
            this.next = next;
        }
  
        public String toString()
        {
            // returns the data in
            // string format
            return data.toString();
        }
    }
  
    // Here top acts as a reference to the Node
    private Node top;
    public boolean isEmpty() { return top == null; }
    public void push(T ele)
    {
        // Every time  when a new element is pushed onto the
        // stack a new Node is created and top is pointed to
        // it
        top = new Node(ele, top);
    }
  
    public T pop()
    {
  
        // check if elements present on Stack or not
        if (top == null)
            return null;
        else {
            // if present do the following
            // Assign the topmost element of
            // stack into a variable
            T element = top.data;
            // make top to point it's next
            // node
            top = top.next;
            // Popped element is returned to
            // the main
            return element;
        }
    }
  
    public T peek()
    {
        // return the element which is
        // at beginning of the stack
        return top.data;
    }
  
    public int size()
    {
        // This method returns the no.of elements present on
        // the stack
        int count = 0;
        Node temp = top;
  
        while (temp != null) {
            // increment count
            count += 1;
            // make temp to point it's
            // next Node
            temp = temp.next;
        }
  
        return count;
    }
  
    public void display()
    {
        // This method displays every element of the Stack
        // LinkedList
        System.out.println(
            "The elements of the stack are: ");
        Node temp = top;
        while (temp != null) {
            // print the data in 'temp'
            System.out.print(temp.data + "->");
            // make temp to point it's
            // next Node
            temp = temp.next;
        }
        // indicates that last Node is not
        // pointing to any Node
        System.out.println("null");
  
        System.out.println();
    }
}
  
// main method
public class GFG {
  
    // main driver method
    public static void main(String[] args)
    {
        // create an object of LinkedStack
        LinkedStack<Double> ls = new LinkedStack<>();
  
        // push an element onto the stack
        // push 10
        ls.push(10.0);
  
        // push 20
        ls.push(20.0);
  
        // display the contents of the stack
        // try to push some more elements
        ls.display();
  
        ls.push(30.0);
        ls.push(40.0);
  
        System.out.println(
            "After pushing 10.0,20.0,30.0,40.0");
  
        ls.display();
  
        // pop element from stack(40.0 is popped
        // out)
        ls.pop();
  
        // 30.0 is popped out
        // printing the stack after poping the elements
        ls.pop();
  
        System.out.println("after pop() operation");
        ls.display();
  
        // display the topmost element of the stack
        System.out.println(
            "current Topmost element of stack: "
            + ls.peek());
  
        // display the no.of elements of the stack
        System.out.println("current size of the stack: "
                           + ls.size());
  
        System.out.println();
  
        // Now create another Object with String Type
        // parameter
        LinkedStack<String> lss = new LinkedStack<>();
  
        // push a String message
        // onto the stack
        lss.push("How's your day?");
        lss.push("geek");
        lss.push("Hello!!");
  
        // Display the contents of the stack
        lss.display();
        lss.pop();
        System.out.println("after pop() operation");
  
        lss.display();
  
        // display the topmost string on
        // the stack
        System.out.println(
            "current Topmost element of stack: "
            + lss.peek());
  
        System.out.println("current size of the stack: "
                           + lss.size());
        // Although the implementation is using generics try
        // yourself and perform the above operations using
        // different datatypes as type parameters..
    }
}


Output

The elements of the stack are: 
20.0->10.0->null

After pushing 10.0,20.0,30.0,40.0
The elements of the stack are: 
40.0->30.0->20.0->10.0->null

after pop() operation
The elements of the stack are: 
20.0->10.0->null

current Topmost element of stack: 20.0
current size of the stack: 2

The elements of the stack are: 
Hello!!->geek->How's your day?->null

after pop() operation
The elements of the stack are: 
geek->How's your day?->null

current Topmost element of stack: geek
current size of the stack: 2

Time and Space Complexity

Time Complexity : O(1)  

For push(), pop(), and peek() operations  because we are just retrieving the contents of the stack which takes constant time, while the operations size() and display() take O(N) time complexity because these methods iterate over all elements of the stack, where ‘N’ is the number of nodes of the stack

Auxiliary space : O(N) 

The space required for the code to store each node(data and reference to the next Node) of the stack is O(1), so if there are ‘N’ nodes the space complexity becomes O(N).  

we can also write the above main method in menu-driven format, here is the code for you (which has Double data type as a type parameter you can change that if you want) 

Java




// main method
public class GFG {
    // main driver method
    public static void main(String[] args)
    {
        // create an object of LinkedStack
        LinkedStack<Double> ls = new LinkedStack<>();
  
        Scanner sc = new Scanner(System.in);
  
        do {
            // As we are writing a menu driven program so
            // user can choose the operation he wants
            System.out.println("-----MENU-----");
  
            System.out.print(
                "1.push\n2.pop\n3.peek\n4.display\n5.size\n6.exit\n");
  
            System.out.println("Enter your choice:");
  
            int choice = sc.nextInt();
  
            switch (choice) {            
              case 1:
                System.out.println("Enter the element to push :");
                Double ele = sc.nextDouble();
                ls.push(ele);
                break;
              
              case 2:
                System.out.print("Poped element: ");
                System.out.println(ls.pop());
                break;
              
              case 3:
                System.out.println("topmost element :");
                System.out.println(ls.peek());
                break;
              
              case 4:
                ls.display();
                break;
              
              case 5:
                System.out.println("Total elements on stack: "+ ls.size());
                break;
              
              case 6:
                System.exit(1);
              
              default:
                System.out.println("Invalid choice!!");
            }
        
      while (true);
    }
}


We can also include an interface in our code that has the abstract methods and it should be placed in its own file and the class should include the keyword ‘implements’ in order to implement the methods of it. 

Here is an example interface for the above example:

Java




public interface IStack<T> {
    // This Interface has the abstract methods
    // to be implemented by the LinkedStack
    // checks whether Stack is empty or not
    boolean isEmpty();
  
    // inserts an element onto the stack
    void push(T ele);
  
    // deletes and returns the beginning element on
    // the stack
    T pop();
  
    // returns the beginning element of the stack
    T peek();
  
    // returns the no.of elements present on stack
    int size();
}




Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads