Tuesday, October 14, 2014

Java Basics

A Brief Summary of the String Class


A Java String contains an immutable sequence of Unicode characters. Unlike C/C++, where string is simply an array of char, A Java String is an object of the class java.lang.
Java String is, however, special. Unlike an ordinary class:
String is associated with string literal in the form of double-quoted texts such as "Hello, world!". You can assign a string literal directly into a String variable, instead of calling the constructor to create a String instance.
The '+' operator is overloaded to concatenate two String operands. '+' does not work on any other objects such as Point and Circle.

String is immutable. That is, its content cannot be modified once it is created. For example, the method toUpperCase() constructs and returns a new String instead of modifying the its existing content.

Static method String.format() (JDK 1.5)
The static method String.format() (introduced in JDK 1.5) can be used to produce a formatted String using C-like printf()'s format specifiers. The format() method has the same form as printf(). For example,
String.format("%.1f", 1.234);   // returns String "1.2"
String.format() is useful if you need to produce a simple formatted String for some purposes (e.g., used in method toString()). For complex string, use StringBuffer/StringBuilder with a Formatter. If you simply need to send a simple formatted string to the console, use System.out.printf(), e.g.,
System.out.printf("%.1f", 1.234);


1.  String Literal vs. String Object

OOP_StringLliteralVsObject.png





There are two ways to construct a string: implicit construction by assigning a string literal or explicitly creating a String object via the new operator and constructor. For example,
String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object
Java has provided a special mechanism for keeping the String literals - in a so-called string common pool. If two string literals have the same contents, they will share the same storage inside the common pool. This approach is adopted to conserve storage for frequently-used strings. On the other hand,String objects created via the new operator and constructor are kept in the heap. Each String object in the heap has its own storage just like any other object. There is no sharing of storage in heap even if two String objects have the same contents.
You can use the method equals() of the String class to compare the contents of two Strings. You can use the relational equality operator '==' to compare the references (or pointers) of two objects. Study the following codes:
s1 == s1;         // true, same pointer
s1 == s2;         // true, s1 and s1 share storage in common pool
s1 == s3;         // true, s3 is assigned same pointer as s1
s1.equals(s3);    // true, same contents
s1 == s4;         // false, different pointers
s1.equals(s4);    // true, same contents
s4 == s5;         // false, different pointers in heap
s4.equals(s5);    // true, same contents
Important Notes:
  • In the above example, I used relational equality operator '==' to compare the references of two String objects. This is done to demonstrate the differences between string literals sharing storage in the common pool and String objects created in the heap. It is a logical error to use (str1 == str2) in your program to compare the contents of two Strings.
  • String can be created by directly assigning a String literal which is shared in a common pool. It is uncommon and not recommended to use the new operator to construct a String object in the heap.

2.  Difference Between String, StringBuilder and StringBuffer Classes


String

String is immutable  ( once created can not be changed )object  . The object created as a String is stored in the  Constant String Pool  .
Every immutable object in Java is thread safe ,that implies String is also thread safe . String can not be used by two threads simultaneously.
String  once assigned can not be changed .

String  demo = " hello " ;
// The above object is stored in constant string pool and its value can not be modified.

demo="Bye" ;     //new "Bye" string is created in constant pool and referenced by the demo variable          
 // "hello" string still exists in string constant pool and its value is not overrided but we lost reference to the  "hello"string

StringBuffer

StringBuffer is mutable means one can change the value of the object . The object created through StringBuffer is stored in the heap .  StringBuffer  has the same methods as the StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread safe .

Due to this it does not allow  two threads to simultaneously access the same method . Each method can be accessed by one thread at a time .

But being thread safe has disadvantages too as the performance of the StringBuffer hits due to thread safe property . Thus  StringBuilder is faster than the StringBuffer when calling the same methods of each class.

StringBuffer value can be changed , it means it can be assigned to the new value . Nowadays its a most common interview question ,the differences between the above classes .
String Buffer can be converted to the string by using
toString() method.

StringBuffer demo1 = new StringBuffer("Hello") ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer("Bye");
// Above statement is right as it modifies the value which is allowed in the StringBuffer

StringBuilder

StringBuilder  is same as the StringBuffer , that is it stores the object in heap and it can also be modified . The main difference between the StringBuffer and StringBuilder is that StringBuilder is also not thread safe.
StringBuilder is fast as it is not thread safe .

StringBuilder demo2= new StringBuilder("Hello");
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder("Bye");

// Above statement is right as it modifies the value which is allowed in the StringBuilder


      String    StringBuffer  StringBuilder
Storage Area Constant String Pool  Heap  Heap
Modifiable No (immutable) Yes( mutable ) Yes( mutable )
Thread Safe Yes No No
Performance Fast Very Slow Fast


The StringBuffer and StringBuilder classes are used when there is a necessity to make a lot of modifications to Strings of characters. The StringBuilder class was introduced as of Java 5 and the main difference between the StringBuffer and StringBuilder is that StringBuilders methods are not thread safe(not Synchronised).
It is recommended to use StringBuilder whenever possible because it is faster than StringBuffer. However if thread safety is necessary the best option is StringBuffer objects.


3.  Benchmarking String/StringBuffer/StringBuilder

The following program compare the times taken to reverse a long string via a String object and a StringBuffer.
// Reversing a long String via a String vs. a StringBuffer
public class StringsBenchMark {
   public static void main(String[] args) {
      long beginTime, elapsedTime;
 
      // Build a long string
      String str = "";
      int size = 16536;
      char ch = 'a';
      beginTime = System.nanoTime();   // Reference time in nanoseconds
      for (int count = 0; count < size; ++count) {
         str += ch;
         ++ch;
         if (ch > 'z') {
            ch = 'a';
         }
      }
      elapsedTime = System.nanoTime() - beginTime;
      System.out.println("Elapsed Time is " + elapsedTime/1000 + " sec (Build String)");
 
      // Reverse a String by building another String character-by-character in the reverse order
      String strReverse = "";
      beginTime = System.nanoTime();
      for (int pos = str.length() - 1; pos >= 0 ; pos--) {
         strReverse += str.charAt(pos);   // Concatenate
      }
      elapsedTime = System.nanoTime() - beginTime;
      System.out.println("Elapsed Time is " + elapsedTime/1000 + " sec (Using String to reverse)");
 
      // Reverse a String via an empty StringBuffer by appending characters in the reverse order
      beginTime = System.nanoTime();
      StringBuffer sBufferReverse = new StringBuffer(size);
      for (int pos = str.length() - 1; pos >= 0 ; pos--) {
         sBufferReverse.append(str.charAt(pos));      // append
      }
      elapsedTime = System.nanoTime() - beginTime;
      System.out.println("Elapsed Time is " + elapsedTime/1000 + " sec (Using StringBuffer to reverse)");
 
      // Reverse a String by creating a StringBuffer with the given String and invoke its reverse()
      beginTime = System.nanoTime();
      StringBuffer sBufferReverseMethod = new StringBuffer(str);
      sBufferReverseMethod.reverse();     // use reverse() method
      elapsedTime = System.nanoTime() - beginTime;
      System.out.println("Elapsed Time is " + elapsedTime/1000 + " sec (Using StringBuffer's reverse() method)");
 
      // Reverse a String via an empty StringBuilder by appending characters in the reverse order
      beginTime = System.nanoTime();
      StringBuilder sBuilderReverse = new StringBuilder(size);
      for (int pos = str.length() - 1; pos >= 0 ; pos--) {
         sBuilderReverse.append(str.charAt(pos));
      }
      elapsedTime = System.nanoTime() - beginTime;
      System.out.println("Elapsed Time is " + elapsedTime/1000 + " usec (Using StringBuilder to reverse)");
 
      // Reverse a String by creating a StringBuilder with the given String and invoke its reverse()
      beginTime = System.nanoTime();
      StringBuffer sBuilderReverseMethod = new StringBuffer(str);
      sBuilderReverseMethod.reverse();
      elapsedTime = System.nanoTime() - beginTime;
      System.out.println("Elapsed Time is " + elapsedTime/1000 + " sec (Using StringBuidler's reverse() method)");
   }
}
Elapsed Time is 332100 usec (Build String)
Elapsed Time is 346639 usec (Using String to reverse)
Elapsed Time is 2028 usec   (Using StringBuffer to reverse)
Elapsed Time is 847 usec    (Using StringBuffer's reverse() method)
Elapsed Time is 1092 usec   (Using StringBuilder to reverse)
Elapsed Time is 836 usec    (Using StringBuidler's reverse() method)
Observe StringBuilder is 2x faster than StringBuffer, and 300x faster than String. The reverse() method is the fastest, which take about the same time for StringBuilder and StringBuffer.

Java 7 Features

1. Automatic resource management with try-with-resources in java 7 (close() method called by JVM) - no catch or finally required

Try-with-resources (originally known as Automatic Resource Management) is a Project Coin proposal that made its way into recent JDK 7 builds. Traditionally, developers had to manually terminate any resources (files, database connections, etc.) they use in applications. It could be difficult keeping track, and not doing so could lead to problems such as resource leaks that could lead to application failures that are hard to debug and triage. Java 7 will now natively support managing resources.

Example:
The following example uses a try-with-resources statement to automatically close a java.sql.Statement object:

public static void viewTable(Connection con) throws SQLException {

    String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";

    try (Statement stmt = con.createStatement()) {
        ResultSet rs = stmt.executeQuery(query);

        while (rs.next()) {
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");

            System.out.println(coffeeName + ", " + supplierID + ", " +
                               price + ", " + sales + ", " + total);
        }
    } catch (SQLException e) {
        JDBCTutorialUtilities.printSQLException(e);
    }
}
The resource java.sql.Statement used in this example is part of the JDBC 4.1 and later API.

Note: A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.


2. In Java 7 it was made possible to catch multiple different exceptions in the same catch block. This is also known as multi catch.

Before Java 7 you would write something like this:

try {

    // execute code that may throw 1 of the 3 exceptions below.

} catch(SQLException e) {
    logger.log(e);

} catch(IOException e) {
    logger.log(e);

} catch(Exception e) {
    logger.severe(e);
}
As you can see, the two exceptions SQLException and IOException are handled in the same way, but you still have to write two individual catch blocks for them.

In Java 7 you can catch multiple exceptions using the multi catch syntax:

try {

    // execute code that may throw 1 of the 3 exceptions below.

} catch(SQLException | IOException e) {
    logger.log(e);

} catch(Exception e) {
    logger.severe(e);
}
Notice how the two exception class names in the first catch block are separated by the pipe character |. The pipe character between exception class names is how you declare multiple exceptions to be caught by the same catch clause.


3. we can use string literals in switch statements.

In the JDK 7 release, developers can use a String object in the expression of a switch statement. The switch statement compares the String object in its expression with the expressions associated with each case label as if it were using the String.equals method. Because of this, the comparison of String objects in switch statements is case-sensitive. The Java compiler generates more efficient byte code from switch statements that use String objects than from chained if-then-else statements.


public static void main(String[] args) {
      String data="JAVA 7";
     
      switch(data)
      {
          case "DOT NET":
              System.out.println("lower case");
              break;
          case "JAVA 7":
              System.out.println("upper case");
              break;
          case "java 8":
          System.out.println("java");
          break;
           default:
                  System.out.println("Otherthan java");
         }
  }

Output : upper case

4. The Diamond Operator

The Diamond Operator reduces some of Java's verbosity surrounding generics by having the compiler infer parameter types for constructors of generic classes. The original proposal for adding the Diamond Operator to the Java language was made in February 2009 and includes this simple example:

For example, consider the following assignment statement:

Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
This is rather lengthy, so it can be replaced with this:
Map<String, List<String>> anagrams = new HashMap<>();