Thursday, 27 July 2023

Strategy Design Pattern in Java with Real-Time Example

     In this post, we will learn the Strategy Design Pattern with a real-world example. For all design pattern articles, refer to Design Patterns.

The Strategy Design Pattern is one of the behavioral design patterns. It is used when there are multiple algorithms available for a specific task, and the client decides which implementation to use at runtime. The Strategy pattern provides greater flexibility, extensibility, and maintainability by allowing algorithms to be selected dynamically.

There are many real-world use cases for the Strategy pattern, such as supporting different payment methods, implementing various sorting algorithms, and many more.

In this article, we will use a GST tax calculation example to understand the Strategy pattern in detail. GST rates vary depending on the type of product. Currently, there are four GST slabs: 5%, 12%, 18%, and 28%. Some products are GST-exempt (0% GST), but for simplicity, we will not consider that case in this example.

Instead of writing the tax calculation logic in multiple conditional statements or tightly coupling it to a single class, we will implement a separate strategy class for each GST slab. This approach makes the code more flexible, readable, reusable, and easier to extend. It also follows the Open/Closed Principle by allowing new tax strategies to be added without modifying existing code.

The first step is to create a common interface. Then, create a separate implementation class for each GST slab, with each class implementing the interface.


TaxCalculation.java

public interface TaxCalculation {
     public Double calculateTax(Double productPrice);
}

Implemented classes, the overriden method calculateTax method logic will differ for each slab.

FivePercentageTax.java

public class FivePercentageTax implements TaxCalculation{

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 5) / 100;
	}

}

TwelvePercentageTax.java

public class TwelvePercentageTax implements TaxCalculation{

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 12) / 100;
	}

}

EighteenPercentageTax.java

public class EighteenPercentageTax implements TaxCalculation {

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 18) / 100;
	}

}

TwentyEightPercentageTax.java

public class TwentyEightPercentageTax implements TaxCalculation {

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 28) / 100;
	}

}

The GSTTaxCalculator class is the main class that contains the calculateGSTTax() method. This method accepts an object of a class that implements the TaxCalculation interface. Using this object, it invokes the calculateTax() method, which executes the corresponding GST tax calculation strategy based on the implementation passed at runtime.

GSTTaxCalculator.java

public class GSTTaxCalculator {
	
     public double taxAmount;

     public void calculateGSTTax(TaxCalculation taxCalculation, double productPrice) {
	   this.taxAmount = taxCalculation.calculateTax(productPrice);
     }
}

StrategyDesignPatternDemo.java is a demo class that demonstrates how the Strategy Design Pattern works. In your application, you simply need to create an instance of the GSTTaxCalculator class, invoke the calculateGSTTax() method, pass an object of a class that implements the TaxCalculation interface, and provide the item price as input.
This is just a simple example to illustrate the Strategy Design Pattern. In a real-world application, you should implement the pattern based on your business requirements and use case.

StrategyDesignPatternDemo.java

public class StrategyDesignPatternDemo {
	
	public static void main(String[] args) {
		
		GSTTaxCalculator gstTaxCalculator = new GSTTaxCalculator();
		
		gstTaxCalculator.calculateGSTTax(new FivePercentageTax(), 250);
		System.out.println("GST tax for 5% slab - "+gstTaxCalculator.taxAmount);
		
		gstTaxCalculator.calculateGSTTax(new TwelvePercentageTax(), 250);
		System.out.println("GST tax for 12% slab - "+gstTaxCalculator.taxAmount);
		
		gstTaxCalculator.calculateGSTTax(new EighteenPercentageTax(), 250);
		System.out.println("GST tax for 18% slab - "+gstTaxCalculator.taxAmount);
		
		gstTaxCalculator.calculateGSTTax(new TwentyEightPercentageTax(), 250);
		System.out.println("GST tax for 28% slab - "+gstTaxCalculator.taxAmount);
	}
}

Output:- GST tax for 5% slab - 12.5
              GST tax for 12% slab - 30.0
              GST tax for 18% slab - 45.0
              GST tax for 28% slab - 70.0


Thank you for visiting the blog.

Tuesday, 25 July 2023

Publicis Sapient Java Technical Lead Interview Questions

      Below is the list of Java Technical Lead interview questions asked at Publicis Sapient during the second round.

1)  Time complexity for HashMap, LinkedHashMap, ArrayList, LinkedList, ConcurrentHashMap.(Answer)

2) Explain ReentrantLock in java (Answer)

3) What is thread pool and explain the executor framework.

4) Explain java 8 features(Answer)

5) What is difference between map and flatMap method in stream(Answer)

6) What is the difference between stream and parallel stream. Explain parallel stream performance.

7) What is association and aggregation in java(Answer)

8)  Explain Solid Design Principles(Answer)

9) Difference between SOA and Microservices (Answer)

10) Explain Design pattern used in Microservices mainly Circuit design pattern and Saga pattern(Answer)

11) How to communicate two microservices ? (Answer)

12) Difference between Kafka and RabitMQ(Answer)

13) Explain the scope of spring beans (Answer)

14) What is the use of spring actuator? (Answer)

15) Explain Spring security used in application(Answer)

16) Explain if you used any cahcing algorithm in application

17) Which annotations included in @SpringBootApplication (Answer)


Thank you for reading the blog.


Reference Posts:-

Monday, 24 July 2023

Java 8 Stream API Coding Interview Questions and Answers

      Before attending a Java interview, it's important to practice Stream API coding questions, as the Stream API is one of the most frequently asked topics in Java 8 interviews.

Below are some commonly asked Java 8 Stream API coding questions and their answers..

1) Write a program to print the list of elements from a list using java 8 stream

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
              List<String> list = Arrays.asList(new String[] {"ABC", "BCD", "CDE"});
	      list.stream().forEach(s -> System.out.println(s));
	}
}

Output:- ABC
              BCD
              CDE

2) Write a program to convert lowercase string element of a list into uppercase.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
     public static void main(String[] args) {
	   List<String> list = Arrays.asList(new String[] {"Abc", "bcd", "cde"});
	   list.stream().map(s-> s.toUpperCase()).forEach(
				s -> System.out.println(s));
     }
}

Output:- ABC
              BCD
              CDE

3) Print a list of strings those start with letter "A" and return updated list.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
		List<String> list = Arrays.asList(new String[] {"Abc", "bcd", "cde"});
		List<String> updatedList = list.stream().filter(s-> s.startsWith("A"))
				.collect(Collectors.toList());
		updatedList.stream().forEach(s -> System.out.println(s));
	}
}

Output:- Abc

4) Write a code to calculate the summation of the integers from the list.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(new Integer[] {1,2,3, 4,5});
		//Using lambda expression
		Integer sum = list.stream().mapToInt(i -> i).sum();
		System.out.println(sum);
		
		//Using Integer valueOf method
		Integer sumOfIntegers = list.stream().mapToInt(Integer::valueOf).sum();
		System.out.println(sumOfIntegers);
		
		//Using Integer intValue method
		Integer sumOfIntegerValue = list.stream().mapToInt(Integer::intValue).sum();
		System.out.println(sumOfIntegerValue);	
	}
}

Output:- 15
              15
              15

5) Create a Map object from List using Stream API

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
		List<String> list = Arrays.asList(new String[] {"Ab", "Bcd", "Ce"});
		Map<String, Integer> map = list.stream().collect(Collectors.toMap(
				s->s, s->s.length()));
		map.forEach((x,v) -> System.out.println("key - "+x+", value - "+v));
	}
}

Output:-
key - Ab, value - 2
key - Ce, value - 2
key - Bcd, value - 3

6) Write a program to list the distinct integers from list or remove duplicates from the list.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(new Integer[] {1, 2, 1,4});
		List<Integer> listWithDistinct = list.stream().distinct().collect(Collectors.toList());
		listWithDistinct.stream().forEach(s-> System.out.println(s));
	}
}

Output:-1
             2
             4

7) Write a program to find the Minimum number from a Stream/list.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
	     List<Integer> list = Arrays.asList(new Integer[] {1, 2,3,4});
	     Integer minNumber = list.stream().mapToInt(s->s).min().getAsInt();
	     System.out.println(minNumber);
	}
}

Output:-1

8) Write a program to find the Maximum number from a Stream/list.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
	     List<Integer> list = Arrays.asList(new Integer[] {1, 2,3,4});
	     Integer maxNumber = list.stream().mapToInt(s->s).max().getAsInt();
	     System.out.println(maxNumber);
	}
}

Output:-4

9) Write a program to sort the given list using java 8 stream.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
	     List<Integer> list = Arrays.asList(new Integer[] {8, 2,3,4});
	     List<Integer> sortedList = list.stream().sorted().collect(Collectors.toList());
	     sortedList.stream().forEach(s-> System.out.println(s));
	}
}

Output:-2
             3
             4
             8

10) Write a program to sort the given list in descending order using stream.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(new Integer[] {8, 2,3,4});
		List<Integer> sortedList = list.stream().sorted(
				Collections.reverseOrder()).collect(Collectors.toList());
		sortedList.stream().forEach(s-> System.out.println(s));
	}
}

Output:-8
             4
             3
             2

11) Write a program to count the total number of integers in the list.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
	     List<Integer> list = Arrays.asList(new Integer[] {8, 2,3,4});
	     long count = list.stream().count();
	     System.out.println(count);
	}
}

Output:-4

12)  Convert List<List<String>> into List<String> using flatMap method.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
	     List<List<Integer>> listListOfStrings = new ArrayList<List<Integer>>();
	     List<Integer> list = Arrays.asList(new Integer[] {8, 2,3,4});
	     listListOfStrings.add(list);
	     //use flatMap method
	     List<Integer> newList = listListOfStrings.stream().flatMap(
				s-> s.stream()).collect(Collectors.toList());
	     newList.stream().forEach(s-> System.out.println(s));
	}
}

Output:-8
             2
             3
             4

13) Group by a list element and display the total count of the element using Collectors groupingBy method.

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
	     List<String> letters = Arrays.asList("A", "B", "C","A", "D", "C", "D");
	     Map<String, Long> mapWithLetterCount = letters.stream().collect(
	                        Collectors.groupingBy(
	                                Function.identity(), Collectors.counting()));  
	     System.out.println(mapWithLetterCount);   
	}
}

Output:- {A=2, B=1, C=2, D=2}

14)  Find the first element from the given list using java 8 stream.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
	     List<String> letters = Arrays.asList("A", "B", "C","A", "D", "C", "D");
	     String firstElement = letters.stream().findFirst().orElse("Default");  
	     System.out.println(firstElement);   
	}
}

Output:-A

15)  anyMatch code example - if any one of the list element matches with given character "A" then return true.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
             List<String> letters = Arrays.asList("A", "B", "C", "D");
	     boolean foundElement = letters.stream().anyMatch(s-> s.equalsIgnoreCase("A"));  
	     System.out.println(foundElement);   
	}
}

Output:-true

16) allMatch code example - if all of the elements matches with the given element say "A" then return true else false.

import java.util.Arrays;
import java.util.List;

public class Java8Stream {
	public static void main(String[] args) {
             List<String> letters = Arrays.asList("A", "B", "C", "D");
	     boolean foundMatches = letters.stream().allMatch(s-> s.equalsIgnoreCase("A"));  
	     System.out.println(foundMatches);   
	}
}

Output:-false

17) Write a program to remove the duplicates from the list using Collectors toSet method.

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Java8Stream {
	public static void main(String[] args) {
	     List<String> letters = Arrays.asList("A", "B", "C", "D", "A", "B");
	     Set<String> nonDuplicateSet = letters.stream().collect(Collectors.toSet());  
	     nonDuplicateSet.stream().forEach(s-> System.out.println(s));
	}
}

Output:-A
             B
             C
             D

     
Thank you for reading the post.

Reference Posts:-

Wednesday, 19 July 2023

Difference Between map() and flatMap() in Java Streams

     The Stream API is one of the most important features introduced in Java 8. A stream is not a data structure, which means it does not store any data. It also does not modify the original data. Instead, it operates on a data source, such as a collection or an array, and processes the data in a convenient and efficient manner.

The Stream API helps you write cleaner, more readable, and more maintainable code while performing operations such as filtering, mapping, sorting, and reducing data.

Let's discuss the usage and differences between the map() and flatMap() methods.

  • Use the map() method when you want to transform each element of a stream into exactly one corresponding element. In other words, one input element is mapped to one output element.

  • Use the flatMap() method when the mapping function returns multiple values (such as a collection or another stream) for each input element, and you want to flatten all those values into a single stream.

map() method example:-

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamMapExamples {
	
	public static void main(String[] args) {
		
		List<String> listOfStrings = Arrays.asList(new String[]{"abc", "bcd", "cde"});
		
		List<String> list = listOfStrings.stream()
				.map( s-> s.toUpperCase()).collect(Collectors.toList());
		
		list.stream().forEach(s-> System.out.println(s));
	}
	
}

the above code will print ABC, BCD and CDE.

flatMap() method example:-

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamflatMapExample {
	
	public static void main(String[] args) {
		
		List<List<String>> listListOfStrings = new ArrayList<List<String>>();
		listListOfStrings.add(Arrays.asList(new String[]{"ABC", "BCD"}));
		listListOfStrings.add(Arrays.asList(new String[]{"CDE", "DEF"}));
		
		List<String> listOfStrings = listListOfStrings.stream().flatMap(s->s.stream()).collect(Collectors.toList());
		
		listOfStrings.stream().forEach(s-> System.out.println(s));
	}

}

The flatMap() method converts a list of lists of strings into a single list of strings by flattening the nested collections into one stream. The above code prints the following values:

ABC, BCD, CDE, and DEF.