Thursday, June 11, 2020

Dynamic Programming

Problems having optimal substructure and overlapping subproblems can be solved by dynamic programming, in which subproblem solutions are Memoized rather than computed again and again. The problems are usually solved in bottom-up manner, were smaller sub-problems are solved first, then the larger sub-problems are solved from them.

Memoization Matrix usually has the column with increasing number from 0 to final result, while the row has the elements which needs to selected for the optimal solution. The first column (and sometimes row) has the 0th column which is a hypothetical condition providing initial values with the matrix.

Levenshtein Distance

Determine the minimum edit distance for converting one string to another string

The Levenshtein distance is a string metric for measuring the difference between two sequences. It is the minimum number of single-character edits (insertions, deletions or substitutions) required to change one word into the other. Here we first create a matrix with Source String as the columns while Destination String as rows. If the row and column character are same then no operation is needed and we directly copy the previous value of the diagonal cell as it is. If the row and column character is different then we find the minimum previous value from the top, side and diagonal, add 1 to it to get the final value as below.
Character Operations: Replace, Delete, Insert.





Below is the code for Levenshtein Distance.
static void editDP(String s1, String s2) 
    { 
        int l1 = s1.length(); 
        int l2 = s2.length(); 
        int[][] DP = new int[l1 + 1][l2 + 1]; 
  
        // initilize by the maximum edits possible 
        for (int i = 0; i <= l1; i++) 
            DP[i][0] = i; 
        for (int j = 0; j <= l2; j++) 
            DP[0][j] = j; 
  
        // Compute the DP matrix 
        for (int i = 1; i <= l1; i++) { 
            for (int j = 1; j <= l2; j++) { 
  
                // if the characters are same 
                // no changes required 
                if (s1.charAt(i - 1) == s2.charAt(j - 1)) 
                    DP[i][j] = DP[i - 1][j - 1]; 
                else { 
  
                    // minimu of three operations possible 
                    DP[i][j] = min(DP[i - 1][j - 1], 
                                   DP[i - 1][j], DP[i][j - 1]) 
                               + 1; 
                } 
            } 
        }  
    } 



Coin Change Problem

When given coins of different denominations and a total amount, find out the number of combinations that make up that amount. Here the assumption is that there are unlimited supply of given coin denominations.
In the below table shows the P(n) for each number, which is the Number of ways representing an Integer as addition of positive Integers.

n Ways P(n)
1 (1) 1
2 (2), (1+1) 2
3 (3), (2+1), (1+1+1) 3
4 (4), (3+1), (2+2), (2+1+1), (1+1+1+1) 5


Lets see below example

Amount = 12
Coins = {1, 2, 5}

ForEach Coin in the given coin denominations i.e. {1, 2, 5}

If Amount >= Coin then
   Combinations[Amount] += Combinations[Amount - Coin]


First initialize the Combinations array with 0 value for all elements.

Combinations when Coin is 1
Set Combinations[0] = 1 when coin is 0, which means using coin 0 to achieve amount 0 there is only 1 combination.

Then we use the above logic to determine the next value of the combination when coin is 1 and amount is 1.
Combinations[1] = Combinations[1-1] + Combinations[1] = Combinations[0] + Combinations[1] = 1 + 0 = 1

Similarly, 
Combinations[2] = Combinations[2-1] + Combinations[2] = Combinations[1] + Combinations[2] = 1 + 0 = 1


0 1 2 3 4 5 6 7 8 9 10 11 12
1 1 1 1 1 1 1 1 1 1 1 1 1


Combinations when Coin is 2
When Amount is 0 or 1 and Coin is 2, the condition (Amount >= Coin) becomes false, so we skip for Amounts 0 and 1.

When Amount is 2 and Coin is 2, we have,
Combinations[2] = Combinations[2-2] + Combinations[2] = Combinations[0] + Combinations[2] = 1 + 1 = 2

The original value of Combinations[2] was 1 from above.
Similarly when Amount is 3 and Coin is 2, we have,
Combinations[3] = Combinations[3-2] + Combinations[3] = Combinations[1] + Combinations[3] = 1 + 1 = 2

Similarly when Amount is 4 and Coin is 2, we have,
Combinations[4] = Combinations[4-2] + Combinations[4] = Combinations[2] + Combinations[4] = 2 + 1 = 3


0 1 2 3 4 5 6 7 8 9 10 11 12
1 1 2 2 3 3 4 4 5 5 6 6 7


Combinations when Coin is 5
When Amount is 0 to 4 and Coin is 5, the condition (Amount >= Coin) becomes false, so we skip Amounts 0 and 4.

When Amount is 5 and Coin is 5, we have,
Combinations[5] = Combinations[5-5] + Combinations[5] = Combinations[0] + Combinations[5] = 1 + 3 = 4

Similarly when Amount is 6 and Coin is 5, we have,
Combinations[6] = Combinations[6-5] + Combinations[6] = Combinations[1] + Combinations[6] = 1 + 4 = 5


0 1 2 3 4 5 6 7 8 9 10 11 12
1 1 2 2 3 4 5 6 7 8 10 11 13


Another example were Amount = 4 and Coins = {1, 2, 3}


Below is the code for Coin Change Problem

int change(int amount, int[] coins) {

  int[] combinations = new int[amount + 1];
  combinations[0] = 1;

  for(int coin : coins) {
    for(int i = 1; i < combinations.length; i++) {
       if(i >= coin) {
         combinations[i] += combinations[i - coin];
       }
    }
  }
}



Longest Common Subsequence (LCS) Problem

Longest Common Subsequence Problem is to find the common subsequences but are not required to occupy consecutive positions with the original sequences.
For example, consider the following sequences, A and B

A = bqdrcvefgh
B = abcvdefgh

Here the length of LCS is 7,
LCS are bdefgh and bcvefgh

We first construct a matrix with columns as characters of string A and rows as characters of string B.
  • If one of the string is empty or both the strings are empty then the length of the longest common subsequence is 0, hence we put zero for both the empty character row and empty character column.
  • When the row character matches with the column character for the cell, then take the previous diagonal value in the matrix and add 1 since there is a match, to get the final value of the cell.
  • When the row character does not match with the column character for the cell, then take the maximum between the above cell and the left cell, to get the final value of the cell.



int longestCommonSubsequence(String A, String B) {

  int m = A.length(), n = B.length();

  int[][] table = new int[m+1][n+1];

  for(int i = 0; i <= m; i++) {
     table[i][0] = 0;
  }

  for(int j = 0; j <= n; j++) {
     table[0][j] = 0;
  }

  for(int i = 1; i <= m; i++) {

     for(int j = 1; j <= n; j++) {

        if(A.charAt(i - 1) == B.charAt(j - 1))
           table[i][j] = table[i - 1][j - 1] + 1;
        else 
           table[i][j] = Math.max(table[i - 1][j], table[i][j - 1]);
     }
  }

  return table[m][n];
}


Subset Sum Problem

Given a set of positive integers and an integer s, find if there is any non-empty subset whose sum is s.

For example set = { 1, 2, 7, 5 }
sum = 8 has subset { 1, 2, 5 }
sum = 4 has no subset

First the given set is sorted in ascending order.

Logic:
Since this is a dynamic programming problem we create a matrix with columns as 0 incrementing by 1 till the sum s. The rows are each element in the example set in a sorted order.

Truth Value = (Truth Value by Excluding New Value) OR (Truth Value by Including New Value)

Truth value by excluding the new value in the current cell comes from the value of upper cell within the matrix.
Truth value by including the new value in the current cell comes from getting the cell value of previous/upper row and the column equal to (sum - new value of the row) within the matrix.
Finally, we return true if we get subset by including or excluding current item else we return false.

To find the subset which gives the sum s, we go to the last cell and backtrack to check were the True value is coming from. If value in the cell above it is False, then it means current cell has become True after including the current element. So include the current element and check for the sum = sum – current element.


public static boolean subSetDP(int[] A, int sum) {
        boolean[][] solution = new boolean[A.length + 1][sum + 1];
        // if sum is not zero and subset is 0, we can't make it 
        for(int i=1; i<=sum; i++){
            solution[0][i]=false;
        }
        // if sum is 0 the we can make the empty subset to make sum 0
        for(int i=0; i<=A.length; i++){
            solution[i][0]=true;
        }
        
        // do for ith item
        for(int i=1; i<=A.length; i++){
            // consider all sum from 1 to sum
            for(int j=1; j<=sum; j++){
            
                // don't include ith element if j-array[i-1] is negative
                if(A[i-1] > j) {
                   //first copy the data from the top
                   solution[i][j] = solution[i-1][j];
                }
                else {
                    // find subset with sum j by excluding or including the ith item
                    solution[i][j] = solution[i-1][j] || solution[i-1][j - A[i-1]];
                }
            }
        }
        return solution[A.length][sum];
    }


Partition Problem

Given a set of positive integers, find if it can be divided into two subsets with equal sum.

Example Set S = {3,1,1,2,2,1}
We can partition S into two partitions each having sum 5.
S1 = {1,1,1,2}
S2 = {2,3}

Another solution could be,
S1 = {3,1,1}
S2 = {2,2,1}

// Return true if there exists a subset of array[0..n) with given sum
private bool subsetSum(int arr[], int n, int sum)
{
	// T[i][j] stores true if subset with sum j can be attained with
	// using items up to first i items
	bool T[n + 1][sum + 1];

	// if 0 items in the list and sum is non-zero
	for (int j = 1; j <= sum; j++)
		T[0][j] = false;

	// if sum is zero
	for (int i = 0; i <= n; i++)
		T[i][0] = true;

	// do for ith item
	for (int i = 1; i <= n; i++)
	{
		// consider all sum from 1 to sum
		for (int j = 1; j <= sum; j++)
		{
			// don't include ith element if j-arr[i-1] is negative
			if (arr[i - 1] > j)
				T[i][j] = T[i - 1][j];
			else
			// find subset with sum j by excluding or including the ith item
				T[i][j] = T[i - 1][j] || T[i - 1][j - arr[i - 1]];
		}
	}

	// return maximum value
	return T[n][sum];
}

// Partition problem - Return true if given array arr[0..n-1] can
// be divided into two subsets with equal sum
public bool partition(int arr[], int n)
{
	int sum = 0;
	for (int i = 0; i < n; i++)
	sum += arr[i];

	// return true if sum is even and array can can be divided into
	// two subsets with equal sum
	return !(sum & 1) && subsetSum(arr, n, sum/2);
}



0/1 Knapsack Problem

We are given a set of items, each with a weight and a value (or profit) and need to determine the number of each item to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. The 0/1 indicates that the item can either be selected or not selected, i.e. items are indivisible.

Sum of the Weights <= Total Weights
Sum of the value should be maximum

Consider the below example were we have items {a, b, c, d, e} with weights and values as below. We need to in the subset with maximum sum of value were sum of their weights should be equal to or less then 9. The quantity of all the items is 1. We create the matrix as below, with the columns as increasing number of weights aka Sum of weights from 0 to the total weight. The rows of the matrix are the sorted using item values.


weight value
a 1 1
b 3 4
c 4 5
d 5 7
e 2 4
item value weight 0 1 2 3 4 5 6 7 8 9
a 1 1 0 1 1 1 1 1 1 1 1 1
e 4 2 0 1 4 5 5 5 5 5 5 5
b 4 3 0 1 4 5 5 8 9 9 9 9
c 5 4 0 1 4 5 5 8 9 10 10 13
d 7 5 0 1 4 5 5 8 9 11 12 13

We cannot achieve the zero weight, using the weights of any items so entire column is assigned the value 0.  For column with weight 1, since item a which has weight 1 can contribute in forming the sum of the weights from 1 to 9, we add 1 to entire row. Now we follow below logic to determine the current value of the cell,

1)   If item weight <= sum of weights,
      value = maximum of(value by excluding the new item, value by including the new item)

To calculate the value by including the new item, we add
  • value of the new item (not the weight)
  • value from above row and the column (sum of weights in column - current item's weight).
2)   If item weight > sum of the weights, copy the value from the above cell.

Use backtracking to determine from were the final value of 13 came to determine the weights or the items included in the result collection.

private int knapSack(int sumWeight, int weights[], int values[]) { 

        int n = values.length;
        
        // K[i][j] stores the maximum value that can be attained with
        // weight less than or equal to j using items up to first i items
        int K[][] = new int[n + 1][sumWeight + 1]; 

	    for (int j = 0; j <= sumWeight; j++) {
		   K[0][j] = 0;
        }

        for (int i = 1; i<= n; i++) { 
        
            // consider all weights from 0 to maximum capacity sumWeight
            for (int j = 0; j<= sumWeight; j++) { 
                    
               	// don't include ith element if j-weights[i-1] is negative
			    if (weights[i-1] > j)
				    K[i][j] = K[i-1][j];
			    else
			    // find max value by excluding or including the ith item
				    K[i][j] = Math.max(K[i-1][j], K[i-1][j-weights[i-1]] + values[i-1]);
            } 
        } 
  
        return K[n][sumWeight]; 
    } 


Rod Cutting Problem

Given a rod of length n and list of pieces of rod of length i where 1 <= i <= n, find the optimal way to cut the rod into smaller rods in order to maximize the profit.

Rod of length = 5
lengths of pieces = {1, 2, 3, 4}
profits of pieces = {2, 5, 7, 8}

If we cut the rod in the given lengths of piece, then profit of each piece is given in corresponding profits set. The rod has to be cut in such a way that we get the maximum profit.


We create the memoization matrix, with column as total length of from 0 to length of the rod, and rows as length of each piece given in the set. Each cell has the profit value for the corresponding piece with the length.

The piece with length 0 is hypothetical condition, hence, entire row's values is 0.
Also if we want to make the total length of 0 for column with sum of length as 0, none of the piece from length 1 to 4 satisfy the condition, hence all entries there are 0.
If we have a piece of length 1 and we want total length to be 1, we need only 1 piece with length 1 to achieve that, hence the profit value of piece 1 is added to the corresponding cell. Similarly, to achieve the total length of 2, we need two pieces of length 1, hence we add profit value of piece 1 twice to corresponding cell. Similar goes for columns 3,4 and 5 with row of piece length 1.

When the row piece length is greater than column total length we copy the cell value from upper row. If the row piece length is less than or equal to column total length, then we use the below logic. Profit by including new piece is,

(Profit of current piece) + 
(Profit of cell with column as (Current Total length - Current piece length) in current row).

Profit = max (Profit by excluding new piece, Profit by including new piece)

profit length 0 1 2 3 4 5
0 0 0 0 0 0 0 0
2 1 0 2 4 6 8 10
5 2 0 2 5 7 10 12
9 3 0 2 5 9 11 14
6 4 0 2 5 9 11 14

// n is the maximum length of the rod
public int rodCut(int[] price, int n)
	{
		// T[i] stores maximum profit achieved from rod of length i
		int[] T = new int[n + 1];
        T[0] = 0;

		// consider rod of length i
		for (int i = 1; i <= n; i++)
		{
			// divide the rod of length i into two rods of length j
			// and i-j each and take maximum
			for (int j = 0; j < i; j++) {
				T[i] = Math.max(T[i], price[j] + T[i - (j + 1)]);
			}
		}

		// T[n] stores maximum profit achieved from rod of length n
		return T[n];
	}



Word Break Problem

Given a string and a dictionary of words, determine if string can be segmented or split into a space-separated sequence of one or more dictionary words.

E.g. dictionary[] = { "this", "th", "is", "famous", "break", "b",
                    "r", "e", "a", "k", "br", "bre", "brea", "ak", "problem"}
string = "Wordbreakproblem"





Saturday, June 6, 2020

Programming Interview - Mathematics Basics


When the order doesn't matter, it is a Combination. When the order does matter it is a Permutation.

There are 2 types of Permutation, repetition is allowed and no repetition allowed.

Permutations with Repetition = n ^ pow(r) = n * n * n * ... (r times)
Here n is the number of things to choose from, and we choose r of them, repetition is allowed, and order matters.

Permutations without Repetition = n! / (n − r)!
Here n is the number of things to choose from, and we choose r of them, no repetitions and order matters.

Similarly there are 2 types of Combination, repetition is allowed and no repetition allowed.

Combinations without Repetition = n! / ( r! * (n − r)! )

Combinations with Repetition = (r + n - 1)! / ( r! * (n − 1)! )


REMEMBER: (a + b) / 2 = a + (b - a) / 2    (Used as (a+b) could overflow Integer's range)

Thursday, May 28, 2020

Programming Interview - Mathematics Problems

Find all factors of the number ?

A number is always divisible by 1 and itself. The smallest factor a number can have is 2, while largest factor would be n/2. But as a * b = number n, were a and b are co-efficient, the pairs of numbers will be duplicated after a = b, i.e. square-root of n. Hence we only need to loop till square-root of n, and add both i and n/i to the list of factors.

Verify if number is a prime number ?

To verify a prime number we only need to loop through from 2 to square-root of number n. As the number n to be non-prime there must be factors "a" and "b" such that a = n / b, i.e. a * b = n. As we observe for example number 36, the factor pairs {1,36} {2,18} {3,12} {4,9} {6,6} {9,4} {12,3} {18,2} {36,1} are repeated after {6,6} which is after square-root of 36, i.e. 6. Hence after square-root of n, the numbers would be either repeated factor-pairs, multiple of other prime numbers.

Also 1 is not regarded as a prime number. 

Fibonacci Sequence

F(n) = { F(n - 1) + F(n - 2)   if n > 1
           {  n                             if n = 0,1 }

0  1  1  2  3  5  8  ...
The first two terms of the series are 0, 1.

Using Recursion: if(n <= 1)  return n;   return fibonacci(n-1) + fibonacci(n-2)

Recursion: Exponential Time
Fibonacci Sequence Recursion: O(2^n)

Iteration: Here we need three variables, the previousNumber, the currentNumber and a temp Number as we cannot assign the new value to currentNumber directly because, we have to first move currentNumber's value to previousNumber.
    System.out.print(previousNumber + ", ");

    for (int i = 1; i < n; i++) {

        newNumber = currentNumber + previousNumber;
        previousNumber = currentNumber;
        currentNumber = newNumber;

        System.out.print(currentNumber + ", ");
    }
  
Modular Exponentiation

Calculate: x^n mod M
Since integer is 32 bit, with 1 bit reserved for sign, the range of integer is -2^31 to 2^31, hence calculating x^n directly will not fit many cases within integer range.

Since (a * b) % M = {(a % M) * (b % M)} % M
x^n % M = (x * x^n-1) % M
        = {(x % M) * (x^n-1 % M)} % M

When n is even,  {(x^n/2 % M) * (x^n/2 % M)} % M
Time complexity is O(log n)

Power(x,n) i.e. x^n
x^n = { x^n/2 * x^n/2  if n is even
        x * x^n-1      if n is odd
        1              if n=0       }

To calculate the time complexity, use the variance of the number being updated and passed to the recursive function.
T(n) = T(n/2) + C
T(n) = T(n/2^k) + K*C    assuming this is done k times.
Hence k is log2(n) which is the time complexity.

Find all factors of the number:

12 = {1,2,3,4,6,12}
Trial Division were we try to divide the number with all the numbers from 1 to n itself.
But 1 and the number itself are its factors. Also since the smallest factor of the number is 2 and largest factor is n/2, there are no factors of the number above n/2. Also if a * b = n, assuming a.b are factors, then when a > sqrt n, then b < sqrt n. Further when a = sqrt n, then a = b = sqrt n. Hence only search factor till square root of number, as remaining are just number/factor.
Divide all the numbers starting from 2 to square-root of n, and add [current-no] with (n / [current-no]) to the factors list. Numbers 1 and n are already added to factors list.

Time complexity is O(sqrt n)


24 = 3 * 2 * 2 * 2

Start dividing the number n by smallest number (starting with 2) such that the remainder is 0. Continue dividing the quotient from previous division until the remainder is non-zero, then select the next number for division of the quotient. The loop continues selecting next smallest number (i) until the (i) becomes greater than square-root of quotient, which indicates that the quotient is a prime number. Since we already know that there cannot be any factors for a number (quotient here) after square-root of that number.

Time complexity is O(sqrt n)

How do implement Sieve of Eratosthenes Algorithms for Prime Number?
How to check if a given year is a leap year in Java?
How to convert a decimal number to binary in Java?
How to reverse given Integer in Java?
How to find the largest prime factor of a given integral number?
How to print Floyd’s triangle?
How to print Pascal’s triangle? (solution)
How to calculate the square root of a given number?


Programming Interview - Core

  1. Sorted array is pre-condition for binary Search. Take two pinter with start = 0, end = n-1 where n is length of the array.
  2. Search a sorted array by repeatedly dividing the search interval in half. 
  3. mid = (start + end) / 2
  4. Case 1:  x == A[mid]   return mid
  5. Case 2:  x < A[mid]    end = mid - 1    (x lies before the mid element, so shift end)
  6. Case 3:  x > A[mid]    start = mid + 1    (x lies after the mid element, so shift start)
  7. Continue till start <= end, (because even when start == end, we have 1 element to check)
If the value of the search key is less than the item in the middle of the interval, narrow the interval to the lower half. Otherwise narrow it to the upper half. Repeatedly check until the value is found or the interval is empty.
  int binarySearch(int array[], int start, int end, int numberToFind);
  
Complexity: (n / 2^k) = 1, were k is no of steps to reach result, while n is length of array. This gives k = log n. Hence the time complexity is O(log n).

Recursive Version:
  • binarySearch(array, start, end, numberToFind)
  • When start > end, then return -1
  • mid = (start + end) / 2
  • Case 1: x == array[mid], then return mid
  • Case 2: x < array[mid],   then call binarySearch(array, start, mid-1, numberToFind)
  • Case 3: x > array[mid],   then call binarySearch(array, mid+1, end, numberToFind)

Binary Search - First Occurrence of the element

We have a sorted array with duplicate elements to find the first occurrence of the element.

Modify the Case1 as below:

result = -1  (initialize the result with -1 indicating that no match found)
Case 1:  x == A[mid]   then  
              result = mid;     (capture the result i.e. the position of the matched element) 
              end = mid - 1    (to find first occurrence of the element x, check if there is one more occurrence of x before matched mid element, hence we shift end before mid)

Finally return result

Binary Search - Last Occurrence of the element

Similar to above we modify the Case1 as below:

Case 1:  x == A[mid]   then  
              result = mid;     (capture the result i.e. the position of the matched element) 
              start = mid + 1    (to find last occurrence of the element x, check if there is one more occurrence of x after the matched mid element, hence we shift start after mid)

Finally return result
Time complexity of both these variations of binary search is O(log n).

Count number of occurrences of element in sorted array

Strategy 1: Loop through the sorted array until there is a match and count until there is no match.
Strategy 2: Find the element in the sorted array using binary search, then first shift left and then shift right to count all the occurrences of the element.
Strategy 3: Find the first occurrence of element using binary search and then the last occurrence of element using binary search, using that determine the count of occurrences since the array is sorted i.e. (Last - First + 1).

Search element in a circular sorted array

Given a sorted circular array were the start element followed by end element lies somewhere in the middle of the array. 
E.g. 12,  14,  18,  21,  3,  6,  8,  9
      low               mid                high

The start element in the above array is 3. 
In the below code, x is the input element to be searched and we need to determine the position of x in the array.

mid = (low + high) / 2

Case1: A[mid] == x, return mid

Case2: A[mid] <= A[high]         // Right half is sorted

2A:    x > A[mid] && x <= A[high]
        low = mid + 1                   // search in right sorted half
Else
       high = mid - 1                    // search in left half

Case 3: A[low] <= A[mid]         // Left half is sorted

3A: x >= A[low] && x < A[mid]
       high = mid - 1                    // search in left sorted half
Else
        low = mid + 1                   // search in right half


Precedence of Operators



(high + low) / 2 is same as low + ((high - low)/2), as low + high can overflow if range exceeds integer.

Memoization
Memoization is an optimization technique used to speed up programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

Sorting



Quick Sort

It is in place sorting.
Average case: O(n log n)
Worst case: n pow 2

1) Select a Pivot.
2) Move the elements lower than pivot to left side, while move elements higher than pivot to right side.

In below example we select the pivot always as the last element.

QuickSort(A, start, end) { 
  if (start < end) {
    pIndex = Partition(A, start, end)
    QuickSort(A, start, pIndex-1)
    QuickSort(A, pIndex+1, end)
  }
}

Partition(A, start, end) {
 pivot = A[end]             // Pivot is always the last element of list
 pIndex = start
 for i=start to end-1 {
   if(A[i] <= pivot) {
     swap(A[i], A[pIndex])
     pIndex = pIndex + 1
   }
 }
 swap(A[pIndex], A[end])
 return
}

Merge Sort

1) Split the list into half, at the mid point. Continue to split the 2 lists each recursively further until only 1 element is present. 
2) Now merge all the splitted list earlier recursively from bottom up such that, the final list at each step is sorted. Note here while merging two lists, we first take original list which was splitted in those two lists in the first place. Loop through both the Left and Right splitter list to check which is greater/less and place them elements in sorted fashion into the original list. Repeat this for all list in each recursive step.

Merge(Left, Right, A) {
  sizeLeft = length(Left)
  sizeRight = length(Right)
  i = j = k = 0

  while(i < sizeLeft && j < sizeRight) {

    if( Left[i] <= Right[j] )  {
       
       A[k] = Left[i]
       k = k + 1
       i = i + 1
    }
    else {

       A[k] = Right[j]
       k = k + 1
       j = j + 1
    }
  }

  // If there are elements remaining in either Left or Right list then simply append to result list

  while(i < sizeLeft) {
     A[k] = Left[i]
     i = i + 1
     k = k + 1
  }
  while(j < sizeRight) {
     A[k] = Right[j]
     j = j + 1
     k = k + 1
  }
}

MergeSort(A) {

  n = length(A)
  if(n < 2) return
  mid = n/2
  left = array of size(mid)
  right = array of size(n - mid)
  for i = 0 to mid - 1
     left[i] = A[i]
  for i = mid to n - 1
     right[i-mid] = A[i]

  MergeSort(left)
  MergeSort(right)
  Merge(left, right, A)
}


Sunday, June 7, 2015

Java 8 Features

Lambda expressions allow to pass in a block of code, a function without a name. The -> separates the parameter from the body of the lambda expression. The parameter of lambda expression does not have a type as the type is inferred from the context of the variable. The lambda method parameters are statically typed. Some different ways of writing lambda expressions areas below:

// 1) empty pair of parentheses, (), can be used to signify that there are no arguments.

Runnable noArguments = () -> System.out.println("Hello World");
// 2) when there is only one argument to the lambda expression we can leave out the parentheses around the arguments.

ActionListener oneArgument = event -> System.out.println("button clicked");
// 3) full block of code, bookended by curly braces ({})

Runnable multiStatement = () -> {
   System.out.print("Hello");
   System.out.println(" World");
};
// 4) This creates a function that adds together two numbers, were the variable called add 
//    isn’t the result of adding up two numbers; it is code that adds together two numbers.

BinaryOperator<Long> add = (x, y) -> x + y;
// 5) providing explicit type to arguments requires to surround the arguments to the lambda expression with parentheses. 
//    The parentheses are also necessary if you’ve got multiple arguments.

BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;

The target type of a lambda expression is the type of the context in which the lambda expression appears—for example, a local variable that it’s assigned to or a method parameter that it gets passed into.

Lambda expressions only use final variables since they capture values, not variables. Although we are not required to declare the variable(s) as final, we cannot use them as nonfinal variable(s) if they are to be used in lambda expressions. If you assign to the variable multiple times and then try to use it in a lambda expression, you’ll get a compile error.

Lambda expressions are statically typed, and these types of lambda expressions are called functional interfaces. A functional interface is an  interface with a single abstract method that is used as the type of a lambda expression.

Table 2-1. Important functional interfaces in Java
Interface name Arguments Returns Example
Predicate<T> T boolean Has this album been released yet?
Consumer<T> T void Printing out a value
Function<T, R> T R Get the name from an Artist object
Supplier<T> None T A factory method
UnaryOperator<T> T T Logical not (!)
BinaryOperator<T> (T, T) T Multiplying two numbers (*)

Java 8 allows you to leave out the types for whole parameters of lambda expressions. Java compiler looks for information close to the lambda expression and uses this information to figure out what the correct type should be. It’s still type checked and provides all the safety that you’re used to, but you don’t have to state the types explicitly. This is what we mean by type inference.

A Predicate is a functional interface that checks whether something is true or false. It is also a lambda expression that returns a value, unlike the previous ActionListener examples.
Predicate<Integer> atLeast5 = x -> x > 5;

Here the return value of the lambda expression is the value its body evaluates to.

BinaryOperator is a functional interface that takes two arguments and returns a value, all of which are of same type. It takes only a generic argument. If no generic argument is specified the code doesn't compile.
BinaryOperator<Long> addLongs = (x, y) -> x + y;

Some of the Key Points on Lambda Expressions:
  • A lambda expression is a method without a name that is used to pass around behavior as if it were data.
  • Lambda expressions look like this: BinaryOperator<Integer> add = (x, y) ? x + y.
  • A functional interface is an interface with a single abstract method that is used as the type of a lambda expression.

Streams

In for loop for collections, the iteration proceeds by creating a new Iterator object and then explicitly calling the hasNext and next methods on the Iterator. Hence its too hard to abstract away the different behavioral operations and is inherently serial in nature.

Streams allow to write collections-processing code at a higher level of abstraction. A Stream is a tool for building up complex operations on collections using a functional approach. The Stream interface contains a series of functions each of which corresponds to a common operation that we might perform on a Collection. The call to stream() returns a Stream which is an equivalent interface with the Iterator in the internal iteration of collection.
long count = allArtists.stream().filter(artist -> artist.isFrom("London")).count();

The operations using Streams API does not change the contents of collection but declared the contents of the Stream. The Stream object returned isn’t a new collection—it’s a recipe for creating a new collection. The filter method of the Stream above keeps only those objects that pass a test by returning either true or false. The call to filter builds up a Stream recipe, but there’s nothing to force this recipe to be used. Methods such as filter that build up the Stream recipe but don’t force a new value to be generated at the end are referred to as lazy. Methods such as count that generate a final value out of the Stream sequence are called eager. If the operation gives back a Stream, it’s lazy; if it gives back another value or void, then it’s eager. The values in the Stream that are operated on are derived from the initial values and the recipe produced by the sequence of Stream calls.

The collect(toList()) is an eager operation that generates a list from the values in a Stream.
List<String> collected = Stream.of("a", "b", "c").collect(Collectors.toList());

The map operation allows to apply a function (say converting a value of one type into another) to a stream of values, producing another stream of the new values. It is an instance of Function.
List<String> collected = Stream.of("a", "b", "hello").map(string -> string.toUpperCase()).collect(toList());

The filter method on the stream allows to check each element of the collection. The Stream after the filter has the elements of the Stream
beforehand, which evaluated to true. It is an instance of Predicate interface.

The flatMap method allows to replace a value with a Stream and concatenates all the streams together. It is a variant of map operation which produces a new Stream object as the replacement. It is associated with functional interface but its return type is restricted to streams and not any value.
// Takes Stream of lists of numbers and returns all the numbers from in the sequences.

List<Integer> together = Stream.of(asList(1, 2), asList(3, 4)).flatMap(numbers -> numbers.stream()).collect(toList());

The max and min methods of stream API finds the maximum or minimum element in the streams. The Comparator is passed to determine the ordering of the elements. The comparing method in java 8 allows to build a Comparator using keys. The getter function for the value allows to get the same element out of both elements being compared. When the max method is called on an empty Stream it returns an Optional value, which represents a value that may exist, or may not.
Track shortestTrack = tracks.stream().min(Comparator.comparing(track -> track.getLength())).get();

The reduce operation is used to generate a single result from a collection of values. It takes the initial count and the lambda expression. The count always starts with 0 which is the count of an empty Stream. The type of the reducer is a BinaryOperator.
int count = Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc + element);

Higher-order functions: A higher-order function is a function that either takes another function as an argument or returns a function as its result. If a functional interface is used as a parameter or return type, then we have a higher-order function. Nearly all the functions that we’ve encountered on the Stream interface are higher-order functions. Comparator is also a functional interface as it has only a single abstract method.

Streams describes the operations on data by saying what transformation is made rather than how the transformation occurs. They help to get towards an idea of side effect–free function. Functions with no side effects don’t change the state of anything else in the program or the outside world. Lambda expressions allow to capture values rather than capturing variables (as variables are final), hence promoting to write code free from side effects. The only exception to this is the forEach method, which is a terminal operation.

Java 8 introduces default methods and static methods on interfaces enabling to have methods with bodies containing code.

Boxed types which wrap up the primitive types are objects and have a memory overhead. An primitive int takes 4 bytes of memory, an boxed type Integer takes 16 bytes. Further an Integer[] take up nearly six times more memory than an int[] of the same size. There is also a computational overhead when converting from a primitive type to a boxed type (boxing) and vice versa (unboxing). The streams library hence differentiates between the primitive and boxed versions of some library functions e.g. mapToLong higher-order function and ToLongFunction.
        If the return type is a primitive, the interface is prefixed with To and the primitive type, as in ToLongFunction. If the argument type is a primitive type, the name prefix is just the type name, as in LongFunction. If the higher-order function uses a primitive type, it is suffixed with To and the primitive type, as in mapToLong. These methods such as mapToLong return specialized streams such as IntStream, DoubleStream and LongStream instead of Stream. The min, max, average, sum along with summaryStatistics methods are all available on all three primitive specialized Stream variants.

While overloading the methods, java infers the type of lambda to be the most specific functional interface when calling these methods.
  • If there is a single possible target type, the lambda expression infers the type from the corresponding argument on the functional interface.
  • If there are several possible target types, the most specific type is inferred.
  • If there are several possible target types and there is no most specific type, you must manually provide a type.

@FunctionalInterface is an annotation that should be applied to any interface that is intended to be used as a functional interface. The new interfaces provide Stream interoperability and are really there to bundle up blocks of code as data. Interfaces such as java.lang.Comparable and java.io.Closeable have only a single method (which depends on the object's internal state) but aren’t normally meant to be implemented by lambda expressions. The @FunctionalInterface annotation can be applied to such interfaces enabling them to be used with lambda expressions.

Default Methods allow to let the implementing classes of the interface use their implementation e.g. the stream method of collection or forEach method on Iterable. Unlike classes, interfaces don’t have instance fields, so default methods can modify their child classes only by calling methods on them. This helps to avoid making assumptions about the implementation of their children. The default method is a virtual method opposite of a static method. The class or concrete method override always takes precedence over the default method. If a child class extends a parent class which in turn implemented an interface with a default method. Then the child class also implemented another interface with the default method of the same signature. But the default method from the parent class takes precedence over the default method from the interface.

When a class implements multiple interface with the same default method it results in the compile error. With the new enhanced super syntax i.e. using the InterfaceName.super variant it’s possible to specify a method from an inherited interface.

Below are the rules for multiple inheritance for default methods.
  1. Any class wins over any interface. So if there’s a method with a body, or an abstract declaration, in the superclass chain, we can ignore the interfaces completely.
  2. Subtype wins over supertype. If we have a situation in which two interfaces are competing to provide a default method and one interface extends the other, the subclass wins.
  3. No rule 3. If the previous two rules don’t give us the answer, the subclass must either implement the method or declare it abstract.
The default methods avoids multiple inheritance of state but rather allows inheritance of blocks of code. Java 8 enables static methods on an interface e.g the of() method of the Stream interface.

Optional is a new core library data type that is designed to provide a better alternative to null. null is often used to represent the absence of a value, and this is the use case that Optional is replacing. The problem with using null in order to represent absence is the dreaded NullPointerException. Optional encourages the coder to make appropriate checks as to whether a variable is null in order to avoid bugs. Second, it documents values that are expected to be absent in a class’s API. The factory method is used to create an Optional instance from a value. The empty factory method of Optional is used to represent Optional as an absent value. Also a a nullable value can be converted into an Optional using the ofNullable method.

A common idiom you may have noticed is the creation of a lambda expression that calls a method on its parameter.
artist -> artist.getName()
Such common idiom can be written using method reference as below:
Artist::getName
The standard form of method reference is Classname::methodName. There are no method brackets, since we are not actually calling the method but providing the equivalent of a lambda expression that can be called in order to call the method. Constructors can also be called using the same abbreviated syntax as below:
(name, nationality) -> new Artist(name, nationality) // original
Artist::new // creating an Artist object
String[]::new // creating String array

Method references automatically support multiple parameters, as long as you have the right functional interface.

Element Ordering
The encounter order is defined depends on both the source of the data and the operations performed on the Stream. When you create a Stream from a collection with a defined order e.g. List, the Stream has a defined encounter order. When we try to map values and there’s a defined encounter order, then that encounter order will be preserved. When there’s no encounter order on the input Stream, there’s no encounter order on the output Stream. Most operations, such as filter, map, and reduce, can operate very efficiently on ordered streams. Although ordering can be removed by using stream's unordered method. The forEachOrdered method provides an ordering guarantee compared to forEach method especially while using parallel streams.

The collector is a general-purpose construct for producing complex values from streams. These can be used with any Stream by passing them into the collect method. The collectors can be statically imported from the java.util.stream.Collectors class.
The toList collector produces java.util.List instances, while the toSet and toCollection collector produces instances of Set and Collection.
List<Integer> numbers = asList(1, 2, 3, 4);
List<Integer> stillOrdered = numbers.stream().map(x -> x + 1).collect(toList());
By calling toList or toSet we don’t get to specify the concrete implementation of the List or Set and the implementation is picked by stream library.

The collector e.g. toCollection can take a function to build a specified type of collection as its argument as below:
stream.collect(toCollection(TreeSet::new));

Also single value can be collected using collector such as maxBy and minBy collectors.
public Optional<Artist> biggestGroup(Stream<Artist> artists) {
   // defines a lambda expression that can map an artist to the number of members
   Function<Artist,Long> getCount = artist -> artist.getMembers().count();
   return artists.collect(maxBy(comparing(getCount)));
}

The averagingInt method takes a lambda expression in order to convert each element in the Stream into an int before averaging the values as below.
public double averageNumberOfTracks(List<Album> albums) {
    return albums.stream().collect(averagingInt(album -> album.getTrackList().size()));
}

A collector partitioningBy takes a stream and partitions its contents into two groups. It uses a Predicate to determine whether an element should be part of the true group or the false group and returns a Map from Boolean to a List of values.
public Map<Boolean, List<Artist>> bandsAndSolo(Stream<Artist> artists) {
 // The method reference Artist::isSolo can be also written as artist -> artist.isSolo()
 return artists.collect(partitioningBy(Artist::isSolo));
}

The groupingBy collector takes a classifier function in order to partition the data similar to the partitioningBy collector which took a Predicate to split it up into true and false values. Below is an example which groups a Stream of albums by the name of their main musician. The groupingBy form below divides elements into buckets. Each bucket gets associated with the key provided by the classifier function, e.g. here its getMainMusician. The groupingBy operation then uses the downstream collector to collect each bucket and makes a map of the results.
public Map<Artist, Long> numberOfAlbums(Stream<Album> albums) {
    return albums.collect(groupingBy(album -> album.getMainMusician(),
    counting()));
}

The mapping collector allows to perform a map-like operation over the collector’s container. The mapping collector needs the collection to store the results, which can be done using the toList collector.
public Map<Artist, List<String>> nameOfAlbums(Stream<Album> albums) {
    return albums.collect(groupingBy(Album::getMainMusician,
    mapping(Album::getName, toList())));
}

In both the above cases, the second collector is used in order to collect a subpart of the final result, hence also called downstream collectors.

Comma separated string from the formatted list can be generated using Collectors.joining which collects the Stream to string as below:
String result =
    artists.stream()
              .map(Artist::getName)
              .collect(Collectors.joining(", ", "[", "]"));

Data Parallelism

Amdahl’s Law is a simple rule that predicts the theoretical maximum speedup of a program on a machine with multiple cores. If we take a program that is entirely serial and parallelize only half of it, then the maximum speedup possible, regardless of how many cores we throw at the problem, is 2×. Given a large number of cores—and we’re already into that territory—the execution time of a problem is going to be dominated by the serial part of that problem

When we have a Stream object, we can call its parallel method in order to make it parallel. If we’re creating a Stream from a Collection, we can call the parallelStream method in order to create a parallel stream from the get-go. Below is the example which calculates the total length of a sequence of albums in parallel.
public int parallelArraySum() {
    return albums.parallelStream()
                 .flatMap(Album::getTracks)
                 .mapToInt(Track::getLength)
                 .sum();
}

The kinds of problems that parallel stream libraries excel at are those that involve simple operations processing a lot of data, such as Simulations. Below is the example of parallel Monte Carlo simulation. Here we first use the IntStream range function to create a stream of size N, then call the parallel method in order to use the parallel version of the streams framework. The twoDiceThrows function simulates throwing two dice and returns the sum of their results, which is used on the data stream using the mapToObj method. All the simulation results are combined using the groupingBy collector. Then the numbers are mapped to 1/N and added using the summingDouble function.
public Map<integer double=""> parallelDiceRolls() {
    double fraction = 1.0 / N;
    return IntStream.range(0, N)
            .parallel()
            .mapToObj(twoDiceThrows())
            .collect(groupingBy(side -> side,
                                summingDouble(n -> fraction)));
}

When calling reduce the initial element could be any value, but for same operation to work correctly in parallel, it needs to be the identity value of the combining function. The identity value leaves all other elements the same when reduced with them. For example, if we’re summing elements with our reduce operation, the combining function is (acc, element) -> acc + element. The initial element must be 0, because any number x added to 0 returns x. Another caveat specific to reduce is that the combining function must be associative. This means that the order in which the combining function is applied doesn’t matter as long the values of the sequence aren’t changed.

The streams framework deals with any necessary synchronization itself, so there’s no need to lock the data structures. If we tried to hold locks on any data structure that the streams library is using, such as the source collection of an operation then it would likely cause issues. Stream also has a sequential method other than the parallel method. When a stream pipeline is evaluated, there is no mixed mode, i.e. the orientation is either parallel or sequential. If a pipeline has calls to both parallel and sequential, the last call wins. Under the hood, parallel streams back onto the fork/join framework. The fork stage recursively splits up a problem, were each chunk is operated upon in parallel and then the results are merged back together in the the join stage.

The common data sources from the core library can be split up into three main groups by performance characteristics:

The good: An ArrayList, an array, or the IntStream.range constructor. These data sources all support random access, which means they can be split up arbitrarily with ease.
The okay: The HashSet and TreeSet. These cannot be decomposed easily with perfect amounts of balance, but most of the time it’s possible to do so.
The bad: Some data structures don’t split well; for example, they may take O(N) time to decompose. Examples here include a LinkedList, which is computationally hard to split in half. Also, Streams.iterate and BufferedReader.lines have unknown length at the beginning, so it’s pretty hard to estimate when to split these sources.

Ideally, once the streams framework has decomposed the problem into smaller chunks, we’ll be able to operate on each chunk in its own thread, with no further communication or contention between threads.

Java 8 includes a couple of other parallel array operations that utilize lambda expressions outside of the streams framework These operations are all located on the utility class Arrays, which also contains a bunch of other useful array-related functionality from previous Java versions

Name Operation
parallelPrefix Calculates running totals of the values of an array given an arbitrary function
parallelSetAll Updates the values in an array using a lambda expression
parallelSort Sorts elements in parallel

The parallelSetAll method is used to easily initialize an array in parallel instead of using a for loop. An array is provided to operate on and a lambda expression, which calculates the value given the index. The array passed into the operation is altered, rather than creating a new copy.
public static double[] parallelInitialize(int size) {
      double[] values = new double[size];
      Arrays.parallelSetAll(values, i -> i);
      return values;
}

The parallelPrefix operation is useful for performing accumulation-type calculations over time series of data. It mutates an array, replacing each element with the sum (or any BinaryOperator) of that element and its predecessors. The below example takes a rolling window over a time series and produces an average for each instance of that window.
public static double[] simpleMovingAverage(double[] values, int n) {
      double[] sums = Arrays.copyOf(values, values.length);
      Arrays.parallelPrefix(sums, Double::sum);
      int start = n - 1;
      return IntStream.range(start, sums.length)
                  .mapToDouble(i -> {
                        double prefix = i == start ? 0 : sums[i - n];
                        return (sums[i] - prefix) / n;
                  })
            .toArray();
}


Sunday, May 10, 2015

EJB Interview Questions

What are benefits of using EJB ?
  • The development of EJB applications is easy as the business logic is separated by the application developer and at the same time the developer can utilize the services of the EJB container.
  • Application Server/ EJB container provides most of the system level services like transaction handling, logging, load balancing, persistence mechanism, exception handling and so on. Developer has to focus only on business logic of the application.
  • EJB container manages life cycle of ejb instances thus developer needs not to worry about when to create/delete ejb objects. 
  • The EJB architecture is compatible with other APIs like servlets and JSPs.
  • EJB allows to build applications using two different layered architectures: the traditional four-tier architecture and domain-driven design (using EJB3). Such isolation of components makes it easy to develop, deploy and manage EJB applications.

What are benefits of using EJB 3 ?
  • It offers seamless integration with other J2ee technologies and a complete stack of server solutions, including persistence, messaging, lightweight scheduling, remoting, web services, dependency injection (DI), and interceptors.
  • EJB 3 enables to develop an EJB component using POJOs and POJIs that know nothing about platform services.
  • EJB 3 allows us to use metadata annotations to configure a component instead of using XML deployment descriptors.
  • JNDI lookups have been turned into simple configuration using metadata-based dependency injection (DI). E.g. @EJB annotation injects EJB into the annotated variable.
  • EJB 3 components are POJOs, and can be easily be executed outside the container using testing frameworks such as JUnit or TestNG.

What are the different types of EJB ?
There are three types of EJB beans, Entity Bean, Session Bean and Message Driven Bean(MDB).

Session Beans: A session bean encapsulates business logic that can be invoked programmatically by a client over local, remote, or web service client views. A session bean instance is available only for the duration of a “unit of work” and is not persistent hence it does not survive a server crash or shutdown. There are two types of session beans: Stateful and Stateless Session Beans.
  • Stateful Session Bean: A stateful session bean automatically saves bean state between client invocations. In a stateful session bean, the instance variables represent the state of a unique client/bean session. Since the client interacts with the bean, such state is often called the conversational state. A session bean is not shared and it can have only one client. When the client terminates, its session bean appears to terminate and is no longer associated with the client. The state is retained for the duration of the client/bean session. If the client removes the bean, the session ends and the state disappears.
  • Stateless Session Bean: A stateless session bean does not maintain a conversational state with the client. When a client invokes the methods of a stateless bean, the bean’s instance variables may contain a state specific to that client but only for the duration of the invocation. When the method is finished, the client-specific state should not be retained. Clients although can change the state of instance variables in pooled stateless beans, and this state is held over to the next invocation of the pooled stateless bean. Except during method invocation, all instances of a stateless bean are equivalent, allowing the EJB container to assign an instance to any client. Because they can support multiple clients, stateless session beans can offer better scalability for applications that require large numbers of clients. A stateless session bean can implement a web service, but a stateful session bean cannot.
@Remote
public interface InventorySessionBeanRemote {
   //add business method declarations
}

@Stateful
public class InventorySessionBean implements InventorySessionBeanRemote {
   //implement business method 
}

@Stateless
public class InventorySessionBean implements InventorySessionBeanRemote {
   //implement business method 
}

Message Driven Beans: A message-driven bean is an enterprise bean that allows Java EE applications to process messages asynchronously. This type of bean normally acts as a JMS message listener which receives and processes JMS messages or other kinds of messages. Clients never invoke MDB methods directly. The message-driven beans unlike session beans are not accessed by the clients through interfaces, but directly using a bean class. Below are some aspects of MDB's:
  • A message-driven bean’s instances retain no data or conversational state for a specific client, hence are stateless.
  • All instances of a message-driven bean are equivalent, allowing the EJB container to assign a message to any message-driven bean instance. The container can pool these instances to allow streams of messages to be processed concurrently.
  • A single message-driven bean can process messages from multiple clients.
  • Message-driven beans are transaction aware and are relatively short-lived.
@MessageDriven(
   name = "QueueMessageHandler",
   activationConfig = {
      @ActivationConfigProperty( propertyName = "destinationType", 
                                 propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty( propertyName = "destination", 
                                 propertyValue ="/queue/InfoQueue")
   }
)
public class InventoryMessageBean implements MessageListener {
 
   // general purpose annotation used to inject anything that the container knows about.
   @Resource
   private MessageDrivenContext mdbContext;  
 
   // injects the dependency as ejb instance into another ejb
   @EJB
   InventoryPersistentBeanRemote inventoryBean;
 
   public InventoryMessageBean(){        
   }
 
   public void onMessage(Message message) {
   }
} 

Entity Beans: An entity bean is a simple POJO having mapping with table. They are used to model persistent data objects. The Entities model lower-level application concepts that high-level business processes manipulate. Entities are object oriented representations of the application data stored in the database and hence survives container crashes and shutdown. JPA entities support OO capabilities, including relationships between entities, inheritance, and polymorphism. Entity beans are transactional.
    The @Entity annotation marks the particular java class as an ejb entity and a persistent object representing the data-store record which is preferred to be serializable. The EntityManager interface reads the ORM metadata for an entity and performs persistence operations. It has the know how to add entities to the database, update stored entities, and delete and retrieve entities from the database. It also helps to execute queries using Query interface. The persistence unit is a reference to the data source in order to access the database. It contains the configuration such as the type of database  and if database tables should be automatically created by the persistence engine.

@Entity
@Table(name="items")
public class Item implements Serializable{
    
   private int id;
   private String name;

   public Item(){ }

   //mark id as primary key with autogenerated value
   //map database column id with id field
   @Id
   @GeneratedValue(strategy= GenerationType.IDENTITY)
   @Column(name="id")
   public int getId() {
      return id;
   }
   ...
}

@Stateless
public class InventoryPersistentBean implements InventoryPersistentBeanRemote {
 
   //pass persistence unit to entityManager.
   @PersistenceContext(unitName="EjbComponentPU")
   private EntityManager entityManager;         

   public void addItem(Item item) {
      entityManager.persist(item);
   }    

   public List<item> getItems() {        
      return entityManager.createQuery("From Items").getResultList();
   }
   ...
}

Explain the life cycle of EJB beans ?
Each type of enterprise bean (stateful session, stateless session, or message-driven) has a different lifecycle.

Lifecycle of a Stateful Session Bean:
  • The client initiates the lifecycle by obtaining a reference to a stateful session bean instance through dependency injection or JNDI lookup.
  • The container performs any dependency injection as specified by metadata annotations on the bean class or by the deployment descriptor.
  • It then calls the PostConstruct lifecycle callback interceptor method(s) for the bean, if any.
  • The container then returns the session object reference to the client. The instance is now in the method ready state and ready for client’s business methods.
  • In the ready stage, the EJB container may decide to deactivate, or passivate, the bean by moving it from memory to secondary storage. The EJB container invokes the method annotated @PrePassivate, if any, immediately before passivating it. If a client invokes a business method on the bean while it is in the passive stage, the EJB container activates the bean, calls the method annotated @PostActivate, if any, and then moves it to the ready stage.
  • At the end of the lifecycle, the client invokes a method annotated @Remove, and the EJB container calls the method annotated @PreDestroy, if any. The bean’s instance is then ready for garbage collection.
     
A business method is executed either in a transaction context or with an unspecified transaction context. When the session bean instance is included in a transaction, the container issues the afterBegin method on it before the business method and the instance becomes associated with the transaction. The container issues beforeCompletion before transaction commit and afterCompletion when the transaction completes.

Lifecycle of a Stateless Session Bean:
  • The container invokes the newInstance method on the session bean class to create a new session bean instance.
  • It then performs any dependency injection as specified by metadata annotations on the bean class or by the deployment descriptor.
  • The container then calls the @PostConstruct lifecycle callback interceptor methods for the bean, if any.
  • The container creates the instance of session bean which is then ready to be delegated a business method call from the clients or a call from the container to a timeout callback method.
  • When the container no longer needs the instance it invokes the @PreDestroy callback interceptor methods, if any. This ends the life of the stateless session bean instance, and the bean’s instance is ready for garbage collection.. 

Lifecycle of a Message Driven Bean:
The EJB container usually creates a pool of message-driven bean instances. For each instance, the EJB container performs following tasks.
  • If the message-driven bean uses dependency injection, the container injects these references before instantiating the instance.
  • The container calls the method annotated @PostConstruct, if any.
  • Like a stateless session bean, a message-driven bean is never passivated and has only two states: nonexistent and ready to receive messages.
At the end of the lifecycle, the container calls the method annotated @PreDestroy, if any. The bean’s instance is then ready for garbage collection.