Sep 29, 2013

Textual description of firstImageUrl

Iterative(non-recursive) inorder traversal of binary tree in Java

In inorder traversal, left subtree is processed first followed by current node and then right subtree. In recursive version of inorder traversal stack(LIFO data structure) maintains references of left and right child.
In iterative version of inorder traversal we requires an external stack where references of left and right child is stored so that after visiting left subtree followed by current node, we can process right subtree. Here, with respect to each node, all left subtree is pushed into stack and process each node in loop. Loop is terminated once stack is empty.Refer following algorithm and sample code.
Algorithm:-  
1. Insert root into stack, if root is not null.
2. Inside loop, do check for empty stack and terminate loop, if stack is empty.
  1. Traverse given tree starting from current root until reaches leaf node, push all intermediate left subtree in stack.
  2. pop elements from stack and process it 
  3. If right child of popped node exist then push right child in stack and right child becomes current root. 
  4. Repeat steps 1 to 3 until stack is empty.
Time and space complexity :- Time complexity is order of O(n) and space complexity is O(n).
Refer following binary tree for inorder traversal:-
Inorder traversal output should be :- 56 11 78 23 43 12 12 98 18
Java code Iterative inorder traversal 
public String iterativeInorderTraversal(Node root) {
 /* java.util.Stack */
 Stack<Node> stack = new Stack<>();
 StringBuffer sbf = new StringBuffer();
 if (root != null) {
  stack.push(root);
  while (true) {
   /* push all left subtree in stack */
   while (root != null) {
    Node lc = root.leftChild;
    /* If left subtree exist, push into stack */
    if (lc != null)
     stack.push(lc);
    /* left child becomes root */
    root = lc;
   }// end inner while loop.

   /*
    * Check for outer loop termination, if stack is empty break
    * loop, Otherwise pop and process element from stack
    */
   if (stack.isEmpty()) {
    break;
   } else {
    root = stack.pop();
    /* process root data */
    sbf.append(root.getData() + " ");

    Node rc = root.getRightChild();
    /* If right child exist, push into stack */
    if (rc != null) {
     stack.push(rc);
    }
    /* Now right child becomes root */
    root = rc;
   }
  }
 }
 return sbf.toString();
}


Complete sample program non-recursive inorder traversal of binary tree in Java

package com.devinline.trees;

import java.util.Stack;

public class IterativeInorderTraversal {

 public String iterativeInorderTraversal(Node root) {
  /* java.util.Stack */
  Stack<node> stack = new Stack&lt;&gt;();
  StringBuffer sbf = new StringBuffer();
  if (root != null) {
   stack.push(root);
   while (true) {
    /* push all left subtree in stack */
    while (root != null) {
     Node lc = root.leftChild;
     /* If left subtree exist, push into stack */
     if (lc != null)
      stack.push(lc);
     /* left child becomes root */
     root = lc;
    }// end inner while loop.

    /*
     * Check for outer loop termination, if stack is empty break
     * loop, Otherwise pop and process element from stack
     */
    if (stack.isEmpty()) {
     break;
    } else {
     root = stack.pop();
     /* process root data */
     sbf.append(root.getData() + " ");

     Node rc = root.getRightChild();
     /* If right child exist, push into stack */
     if (rc != null) {
      stack.push(rc);
     }
     /* Now right child becomes root */
     root = rc;
    }
   }
  }
  return sbf.toString();
 }

 public static void main(String[] args) {
  IterativeInorderTraversal itrInObj = new IterativeInorderTraversal();
  Node root = itrInObj.new BinaryTree().createTree();
  String nodesStr = itrInObj.iterativeInorderTraversal(root);
  System.out.println("Iterative inorder traversal:-  " + nodesStr);
 }

 class BinaryTree {
  Node root;

  public BinaryTree() {
   root = null;
  }

  public Node createTree() {
   if (root == null) {
    root = new Node(12);
   }
   root.setLeftChild(new Node(23));
   root.setRightChild(new Node(18));
   root.getLeftChild().setLeftChild(new Node(11));
   root.getLeftChild().setRightChild(new Node(43));
   root.getRightChild().setLeftChild(new Node(12));
   root.getLeftChild().getLeftChild().setLeftChild(new Node(56));
   root.getLeftChild().getLeftChild().setRightChild(new Node(78));
   root.getRightChild().getLeftChild().setRightChild(new Node(98));
   return root;
  }
 }

 class Node {

  private int data;
  private Node leftChild;
  private Node rightChild;

  public Node(int data) {
   this.data = data;
   leftChild = null;
   rightChild = null;
  }

  public int getData() {
   return data;
  }

  public void setData(int data) {
   this.data = data;
  }

  public Node getLeftChild() {
   return leftChild;
  }

  public void setLeftChild(Node leftChild) {
   this.leftChild = leftChild;
  }

  public Node getRightChild() {
   return rightChild;
  }

  public void setRightChild(Node rightChild) {
   this.rightChild = rightChild;
  }
 }

}
=========Sample output=============
Iterative inorder traversal:- 56 11 78 23 43 12 12 98 18
=================================

Sep 27, 2013

Write to a file in Java - BufferedOutputStream and BufferedWriter

In Java Write operation can be performed using FileOutPutStream and FileWriter. For writing streams of character, FileWriter is preferred and FileOutputStream is used for binary data like images.
FileWriter -  writing streams of characters 
FileOutputStream -  writing streams of raw bytes 

Write into file using FileOutputStream :- 

FileOutputStream is used to write binary data preferably. FileOutputStream extends OutputStream class and when an instance of  FileOutputStream(file,boolean) is created, a file descriptor object is created internally. File descriptor acts as an handle to the underlying machine-specific structure representing an open file. i.e: File descriptor binds stream with the file being used for write operation. Constructor of FileOutputStream takes filename and boolean(optional - indicating streams that bytes will be written to the end of the file or at the beginning). Default value of second parameter is false(stream will add bytes at beginning). However, if true is passed bytes are added at end of file.
Following sample program read and input image (binary input) and write to a new file. Here we have two methods:- writeBinaryStreamSlowestAndSimple and writeBinaryStreamEfficient. First one most in efficient one because input is not buffered, however in second one input stream is buffered and it is more efficient. Always prefer to buffer input/output stream before using it. Sample output below shows why we should prefer to use buffer with stream. Without buffer it write operation took 88 milliseconds and with buffering it just took 5 millisecond.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;

public class FileWriteOperationBinaryDataInput {

 private static Scanner scn;

 // Without buffered input:- Read input file and write to output file
 public static void writeBinaryStreamSlowestAndSimple(File outputFile,
   File inputFile) {
  int byteCoint;
  Long starttime = System.currentTimeMillis();
  try {
   FileInputStream is = new FileInputStream(inputFile);
   // Creates a file descriptor
   FileOutputStream os = new FileOutputStream(outputFile);
   while ((byteCoint = is.read()) != -1) {
    os.write(byteCoint);
   }
   is.close();
   os.close();

  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out.println("Total time spent in writing "
    + "without buffered input is (in millisec) "
    + (System.currentTimeMillis() - starttime));

 }

 // With buffered input:- Read input file and write to output file
 public static void writeBinaryStreamEfficient(File outputFile,
   File inputFile) {
  int byteCoint;
  Long starttime = System.currentTimeMillis();
  try {
   FileInputStream is = new FileInputStream(inputFile);
   // Buffered input stream and loop over buffered result
   BufferedInputStream bis = new BufferedInputStream(is);

   FileOutputStream os = new FileOutputStream(outputFile);
   BufferedOutputStream bos = new BufferedOutputStream(os);
   while ((byteCoint = bis.read()) != -1) {
    bos.write(byteCoint);
   }

//Closes this file input/output stream and releases any system resources associated with the stream.
   is.close(); 
   os.close();

  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out.println("Total time spent in writing "
    + "with buffered input is (in millisec) "
    + (System.currentTimeMillis() - starttime));

 }

 public static void main(String[] args) {
  System.out.println("Enter choice 1 or 2: ");
  scn = new Scanner(System.in);
  int choice = scn.nextInt();
  switch (choice) {
  case 1:
   writeBinaryStreamSlowestAndSimple(new File(
     "E:\\devline_logo_new.png"), new File(
     "E:\\devline_logo.png"));
   break;
  case 2:
   writeBinaryStreamEfficient(new File("E:\\devline_logo_new.png"),
     new File("E:\\devline_logo.png"));
   break;
  default:
   break;
  }

 }
}
===========Sample output==================
Enter choice 1 or 2:
1
Total time spent in writing without buffered input is (in millisec) 88

Enter choice 1 or 2:
2
Total time spent in writing with buffered input is (in millisec) 5
===========================================

Write into file using FileWriter :-

FileWriter is most convenient to use for text based write operation, FileWriter extends OutputStreamWriter(a bridge from character streams to byte streams) and FileWriter internally uses write() operaion of OutputStreamWriter.
On each invocation of a write() method in turn invokes encoding converter on the given character(s) and the resulting bytes are accumulated in a byte buffer before being written to the underlying output stream, write() operation is very costly stream is not wrapped in buffer.
In order to avoid frequent converter invocations, it is recommended to wrap Outputstream/FileWriter in BufferedWriter. Below sample program shows the differences of wrapping or not wrapping FileWriter in BufferedWriter.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class FileWriteOperationTextDataInput {

 private static BufferedReader br;
 private static FileWriter fw;
 private static FileReader fr;
 private static Scanner scn;

 // Without buffered input:- Read input file and write to output file
 public static void writeTextWithoutBufferedInput(File outputFile,
   File inputFile) {
  int readCount;
  Long starttime = System.currentTimeMillis();
  try {
   fr = new FileReader(inputFile);
   fw = new FileWriter(outputFile);
   while ((readCount = fr.read()) != -1) {
    fw.write(readCount);
   }
   fr.close();
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }

  System.out
    .println("Total time spent in write operation " +
      "without buffered input(in milliseconds)  "
      + (System.currentTimeMillis() - starttime));
 }

 // With buffered input:- Read input text file and write to output file
 public static void writeTextWithBufferedInput(File outputFile,
   File inputFile) {
  int readCount;
  Long starttime = System.currentTimeMillis();
  try {
   FileReader fr = new FileReader(inputFile);
   br = new BufferedReader(fr);
   fw = new FileWriter(outputFile);
   BufferedWriter bwr = new BufferedWriter(fw);
   while ((readCount = br.read()) != -1) {
    bwr.write(readCount);
   }
   br.close();
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out
    .println("Total time spent in write operation" +
      " with buffered input(in milliseconds)  "
      + (System.currentTimeMillis() - starttime));
 }

 public static void main(String[] args) {
  System.out.println("Enter choice 1 or 2: ");
  scn = new Scanner(System.in);
  int choice = scn.nextInt();
  switch (choice) {
  case 1:
   writeTextWithoutBufferedInput(new File("E:\\output.xml"), new File(
     "E:\\input.xml"));
   break;
  case 2:
   writeTextWithBufferedInput(new File("E:\\output.xml"), new File(
     "E:\\input.xml"));
   break;
  default:
   break;
  }

 }
}
=========== Sample output=============
Enter choice 1 or 2:
1
Total time spent in write operation without buffered input(in milliseconds)  68
Enter choice 1 or 2: 
2
Total time spent in write operation with buffered input(in milliseconds)  27
===================================

Write operation in append mode :-  

Both class FileWriter and FileOutputStream support writing file in append mode- it means on each call of write method streams(character or byte) are appended at end of file and previous written data persist. Below sample program uses both class and shows how to perform write operation in append mode. On execution of following program(two times one for each case) both content is written to file, as shown in sample output.

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class FileWriteOperationAppendMode {
 private static Scanner scn;
 private static BufferedWriter bw;
 private static FileWriter fw;
 static private File outoutFile = new File("E:\\output.txt");

 // write text using FileOutputStream - In append mode
 // bytes will be written to the end of the file rather than the beginning.
 public static void writeTextUsingFileOutputStreamInAppendMode(
   String inputText, File outputFile) {
  try {
   // Creates a file descriptor
   FileOutputStream fos = new FileOutputStream(outputFile, true);
   bw = new BufferedWriter(new OutputStreamWriter(fos));
   bw.append(inputText);
   bw.newLine();
   bw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }

 }

 // write text using FileWriter, In append mode
 // Characters written to the end of the file rather than the beginning.
 public static void writeTextUsingFileWriterInAppendMode(String inputText,
   File outputFile) {
  try {
   fw = new FileWriter(outputFile, true);
   fw.append(inputText);
   fw.close();
  } catch (IOException e) {
   e.printStackTrace();
  }

 }

 public static void main(String[] args) {
  System.out.println("Enter choice 1 or 2: ");
  scn = new Scanner(System.in);
  int choice = scn.nextInt();

  switch (choice) {
  case 1:
   for (int i = 0; i < 5; i++) {
    writeTextUsingFileWriterInAppendMode("inputViaWriter " + i,
      outoutFile);
   }

   break;
  case 2:
   for (int i = 0; i < 5; i++) {
    writeTextUsingFileOutputStreamInAppendMode(
      "inputViaOutputStream " + i, outoutFile);
   }

   break;
  default:
   break;
  }

 }
}
========Sample output==================
Enter choice 1 or 2:
1
Enter choice 1 or 2: 
2
Output.txt content:- 
inputViaWriter 0inputViaWriter 1inputViaWriter 2inputViaWriter 3inputViaWriter 4
inputViaOutputStream 0
inputViaOutputStream 1
inputViaOutputStream 2
inputViaOutputStream 3
inputViaOutputStream 4
=======================================

Sep 23, 2013

Get Metadata of file in Java - getFileSize(), getLastModified(), setLastModified()

Metadata of file in Java can be obtained using File class methods:
length() - for getting size of file (In bytes)
lastModified() - get last modified time of  file in milliseconds( long value representing the time the file was last modified, measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970))
setLastModified(long time) - set last modified time of a file 

Below sample program shows uses these file methods and display size/last modified time. I have executed this program in Ubuntu. It will work in windows slight modification(uncomment File object creation code in Windows and comment current one) 
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * @author devinline
 * 
 */
public class FindMetaData {

 public static void getLastModifiedDate(File file) {

  SimpleDateFormat dateFormatter = new SimpleDateFormat(
    "yyyy-MM-dd HH:mm:ss");
  System.out.println("last modified time of file is "
    + dateFormatter.format(file.lastModified()));
 }

 public static void setLastModifiedDate(File file) {
  Calendar calendar = Calendar.getInstance();
  file.setLastModified(calendar.getTimeInMillis());
  System.out.println("Call getModifiedtime method again "
    + "after making today's date as moified date ");
  getLastModifiedDate(file);
 }

 public static void getFileSize(File file) {
  System.out.println("File Size in bytes and kilo bytes are:: "
    + file.length() + " bytes\tand " + (file.length() / 1024)
    + " Kilobytes");
 }

 public static void main(String[] args) {
  /*
   * In Windows we can have File file = new File(
   * "E:\\org.jacoco.agent-0.7.2.201409121644-runtime.jar");
   */
  File file = new File(
  "/home/zytham/Downloads/org.jacoco.agent-0.7.2.201409121644-runtime.jar");

  // get file size
  getFileSize(file);
  // get last modified
  getLastModifiedDate(file);
  // set last modified and disply agian modified date
  setLastModifiedDate(file);

 }

}
=======Sample output===========
File Size in bytes and kilo bytes are:: 286862 bytes and 280 Kilobytes
last modified time of file is 2012-02-09 02:03:45
Call getModifiedtime method again after making today's date as moified date
last modified time of file is 2013-10-10 06:10:12
============================

Sep 22, 2013

Textual description of firstImageUrl

Iterative(non-recursive) preorder traversal of binary tree in Java

In preorder traversal, each node is processed before either of its sub-tree(left and right). Once current node is processed, left sub-tree is processed and control return back to current node and then right sub-tree is processed. In recursive version of preorder traversal stack(LIFO data structure) maintains references of left and right child.
In iterative version of preorder traversal, we need an external stack where references of left and right child is stored so that after visiting left subtree we can process right subtree. The catch here is - first insert right subtree followed by left subtree because, we have to process left subtree first then right subtree.(Insertion in stack should be in opposite order, remember LIFO property of stack).
Algorithm:-
1. Insert root into stack if root is not null.
2. Loop until stack is not empty
  1. pop an element from stack  and process its data (Here added in string buffer)
  2. If popped elements right and left child exist, push them in stack - right child first followed by left child
3. Do check, for empty state of stack and repeat step 2.
4. On while loop exit. return string with nodes traversal.
Time and space complexity :- Time complexity is order of O(n) and space complexity is O(n).
Refer following binary tree used for preorder traversal.

Preorder traversal output should be :-    12 23 11 56 78 43 18 12 98
Java code Iterative preorder traversal:
public String iterativePreorderTraversal(Node root) {
 /* java.util.Stack */
 Stack<Node> stack = new Stack<>();
 StringBuffer sbf = new StringBuffer();

 if (root != null) {
  /* push root into stack if root is not null */
  stack.push(root);
  /* Loop until stack is not empty */
  while (!stack.isEmpty()) {
   root = stack.pop();
   /* process root data */
   sbf.append(root.getData() + " ");
   Node lc = root.getLeftChild();
   Node rc = root.getRightChild();

   /* If right child exist, push into stack */
   if (rc != null) {
    stack.push(rc);
   }
   /* If left child exist, push into stack */
   if (lc != null) {
    stack.push(lc);
   }
  }// End while loop
 }
 return sbf.toString();
}

Complete sample program for non-recursive preorder traversal in Java

package com.devinline.trees;

import java.util.Stack;

public class IterativePreorderTraversal {

 public String iterativePreorderTraversal(Node root) {
  /* java.util.Stack */
  Stack stack = new Stack<>();
  StringBuffer sbf = new StringBuffer();

  if (root != null) {
   /* push root into stack if root is not null */
   stack.push(root);
   /* Loop until stack is not empty */
   while (!stack.isEmpty()) {
    root = stack.pop();
    /* process root data */
    sbf.append(root.getData() + " ");
    Node lc = root.getLeftChild();
    Node rc = root.getRightChild();

    /* If right child exist, push into stack */
    if (rc != null) {
     stack.push(rc);
    }
    /* If left child exist, push into stack */
    if (lc != null) {
     stack.push(lc);
    }
   }// End while loop
  }
  return sbf.toString();
 }

 public static void main(String[] args) {
  IterativePreorderTraversal itrPreObj = new IterativePreorderTraversal();
  Node root = itrPreObj.new BinaryTree().createTree();
  String nodesStr = itrPreObj.iterativePreorderTraversal(root);
  System.out.println("Iterative preorder traversal:-  " + nodesStr);
 }

 class BinaryTree {
  Node root;

  public BinaryTree() {
   root = null;
  }

  public Node createTree() {
   if (root == null) {
    root = new Node(12);
   }
   root.setLeftChild(new Node(23));
   root.setRightChild(new Node(18));
   root.getLeftChild().setLeftChild(new Node(11));
   root.getLeftChild().setRightChild(new Node(43));
   root.getRightChild().setLeftChild(new Node(12));
   root.getLeftChild().getLeftChild().setLeftChild(new Node(56));
   root.getLeftChild().getLeftChild().setRightChild(new Node(78));
   root.getRightChild().getLeftChild().setRightChild(new Node(98));
   return root;
  }
 }

 class Node {

  private int data;
  private Node leftChild;
  private Node rightChild;

  public Node(int data) {
   this.data = data;
   leftChild = null;
   rightChild = null;
  }

  public int getData() {
   return data;
  }

  public void setData(int data) {
   this.data = data;
  }

  public Node getLeftChild() {
   return leftChild;
  }

  public void setLeftChild(Node leftChild) {
   this.leftChild = leftChild;
  }

  public Node getRightChild() {
   return rightChild;
  }

  public void setRightChild(Node rightChild) {
   this.rightChild = rightChild;
  }
 }

}
============Sample output===============
Iterative preorder traversal:-  12 23 11 56 78 43 18 12 98
======================================

Sep 21, 2013

Textual description of firstImageUrl

Java puzzle - Set 3

Question 1:  What will be output of below sample program? 
public class Multicast {
 /**
  * devinline.com
  * Puzzle reference : Java puzzlers 
  */
 public static void main(String[] args) {
  System.out.println((byte) -1); // int to byte
  System.out.println((char) (byte) -1); // byte to char
  System.out.println((int) (char) (byte) -1); // char to int
 }
}

Sample output:-
-1
?
65535
Explanation:- In first SOP int is cast into byte (narrowing primitive conversion).Since java represents negative integer in 2's complement form, so all 32 bits for -1 is 1. When it is narrowed down to byte only 8 bits are preserved other bits are discarded, original value -1 is still preserved(sign indicating bits are discarded). Refer following diagram.
Before going ahead we should consider following guideline regarding when sign extension is performed:-
Sign extension is performed if the type of the original value is signed; zero extension if it is a char, regardless of the type to which it is being converted.

In second SOP signed byte is cast into unsigned 16 bit char. Here signed bit is propagated for higher order 8 bits and 16 bits char with all 1's is formed.(sign extension is performed)
Similarly, in third SOP a char is converted into signed integer and zero extension is performed.Value of integer is retained as 65535.
Question 2:  What will be output of below sample program? 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class CompundOperator {
 /**
 * devinline.com 
 * Puzzle reference : Java puzzlers
 */
 public static void main(String[] args) {
  short x = 0;
  int i = 123456;
  x = x + i;
  System.out.println(x += i);
 }
}

Sample output:-
Compilation error. Type mismatch: cannot convert from int to short (Line # 9)

Explanation
:-
An int value(i) is assigned to short(x) and it may cause possible loss of precision, so compilation error reported.

Now lets comment line # 9 and again execute the above sample program.
What will be the output after commenting line # 9 ? Output:   -7616

Explanation
:- 123456 is converted into -7616 because compound assignment expressions automatically cast the result of the computation they perform to the type of the variable on their left-hand side. Here 123456 value is cast into byte and higher order bits truncated and since leftmost bit is 1 so it indicates negative number -7616.

Question 3: What will be output of below sample program? Hint:- a char is an unsigned 16-bit primitive integer.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class SOP {

 /**
  * devinline.com
  */
 public static void main(String args[]) {
  System.out.println("D");
  System.out.println("D" + "I");
  System.out.println('D');
  System.out.print('D' + 'I');
 }

}

Sample output
:-
D
DI
D
141

Explanation:- Class PrintStream has overloaded version of println() method which takes argument of type String, char, int, float, etc and display string representation of the same.
In first SOP D is treated as String and displays D. Similarly, in second SOP two strings are concatenated and displayed as DI.
In third SOP, a char is argument of function println(), it prints a character and then terminate the line.
What about 4th SOP, their is an expression with + operator and none of the operand is String. So + operator will try to evaluate the given expression and char is promoted to int type. Conversion of unsigned int(char) to int allows zero padding in higher order bits.(16 bit char to 32 bit int with higher order padded with 0). D -> 68 and I-> 73 => 68+73= 141.

Question 4. What will be output of below sample program?

public class SOPInteger {

 /**
  * devinline.com
  */
 public static void main(String args[]) {
  System.out.println("2 + 2 = " + 2 + 2);
  System.out.println("2 + 2 = " + (2 + 2));
  System.out.println("" + 'D' + 'I');
                System.out.println('D' + 'I'+" means devinLine");
 }

}
Sample output:-
2 + 2 = 22
2 + 2 = 4
DI
141 means devinLine

Explanation:- Java does not support operator overloading except when + is used with Strings, + operator can be used as concatenation operator(String conversion on both of its operands and then to concatenate the resulting strings). Function println() calls internally toString() method and represent its argument as String and if expression inside println() starts with a string then + operator will append followed elements to the starting string. taking consideration of all above concept, lets see each SOP. 
In first SOP, expression starts with string so + operator act as concatenation operator. It will treat followed 2+2 as string rather than int.
In second SOP, expression starts with string and its followed + act as concatenation operator. However, followed 2+2 is inside ( ) so first 2+2 is evaluated followed by it is concatenated with previous string. 
Similarly, in third SOP, statement starts with an empty string so followed chars are appended with this empty string "".
In fourth SOP, Since expression starts with a char not a string so + operator will not act as concatenation operator. It will try to add both char type and chars are promoted to int.(See previous question for more detail). First sum is computed and followed by string is appended.

Question 5. What will be output of below sample program? 
package com.devinline.puzzles;

public class ToStringTraps {

/**
 * devinline.com
 */
public static void main(String[] args) {
 char[] chArr = { 'D', 'E', 'V', 'I', 'N', 'L', 'I', 'N', 'E' };
 System.out.println(chArr);
 System.out.println("Output is " + chArr);
 System.out.println("Output is " + chArr.toString());
 System.out.println("Output is " + String.valueOf(chArr));

 }
}

Sample output:-
DEVINLINE
Output is [C@1888759
Output is [C@1888759
Output is DEVINLINE

Explanation:- As mentioned earlier + operator can be used as concatenation operator(String conversion on both of its operands and then to concatenate the resulting strings).
Output of 1st SOP is expected, println() prints string representation of char array.
What happens in second SOP, "chArr" is converted into String and java.lang.Array class inherit toString() method from Object class and toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
 chArr.getClass().getName() + '@'+ Integer.toHexString(chArr.hashCode())
Here getClass().getName() for class object char[] gives string "[C" followed by @ and finally hashcode value 1888759(which might differ if you execute above sample program). So output of 2nd SOP is concentration of first string and chArr string value - Output is [C@1888759
Similarly, in 3rd SOP to.String() of chArr is used so result would be same as above.
Finally, we get intended result in 4th SOP, String.valueOf() explicitly convert the array to a string before concatenation.