Friday 14 September 2018

String interning

String is a sequence of characters, you can define a string using String class.

There are two ways to define a string.
a.   Using literal notation
b.   Using new keyword

Using literal notation
Enclose the string in double quotes and assign it to the string variable.

Example
String message1 = "Hello World";

Using new keyword
Just like how you create an object in Java, you can create a string using new keyword. String class provides below constructors to define String object.

public String()
public String(String original)
public String(char value[])
public String(char value[], int offset, int count)
public String(int[] codePoints, int offset, int count)
public String(byte bytes[], int offset, int length, String charsetName)
public String(byte bytes[], int offset, int length, Charset charset)
public String(byte bytes[], String charsetName)
public String(byte bytes[], Charset charset)
public String(byte bytes[], int offset, int length)
public String(byte bytes[])
public String(StringBuffer buffer)
public String(StringBuilder builder)
String(char[] value, boolean share)

Example
String message1 = new String("Hello World");

String literal pool
String literal (or) constant pool is a specialized memory that stores the string literals. String literal pool is stored in application heap memory.

String literal pool and literal notation
Whenever you create a string using literal notation. It follows the below process.
a.   It checks whether same string exists in the literal pool or not.
b.   If the string exists in literal pool, then the same is returned, else it places this string in literal pool and return the reference.

Let’s see it by an example.

Step 1:  I am going to define a string "Hello World" using literal notation.





Since there is no string "Hello World" in pool, java run time creates the one and return the reference.

Now when you try to create other string data with the content  "Hello World", Java run time environment return the reference to the one we created in step 1.


What is String interning?
String interning is a process of storing the exactly one copy of the string in literal pool.

String Literal Pool Vs new object creation
Whenever new String object is defined, then Java run time environment creates new object in the heap memory and place a copy of the string value in String literal pool, only if it not exists in the pool already.

== operator with literals and string objects
== operator return true, if the references are pointing to same object, else false.

Application.java
package com.sample.app;

public class Application {

 public static void main(String args[]) {
  String s1 = "Hello World";
  String s2 = "Hello World";
  String s3 = new String("Hello World");

  System.out.println("s1 Reference Address => " + System.identityHashCode(s1));
  System.out.println("s2 Reference Address => " + System.identityHashCode(s2));
  System.out.println("s3 Reference Address => " + System.identityHashCode(s3));

  System.out.println("\n(s1 == s2) : " + (s1 == s2));
  System.out.println("(s1 == s3) : " + (s1 == s3));
 }
}

Output
s1 Reference Address => 2018699554
s2 Reference Address => 2018699554
s3 Reference Address => 1311053135

(s1 == s2) : true
(s1 == s3) : false

As you see the output, Since I defined variables s1 and s2 using literal notation, they are pointing to same address, where as s3 is created as string object, it has separate address. Thats the reason for (s1 == s2) : true, (s1 == s3) : false.

If you want to compare the content of the strings, then use equals() method.


Application.java
package com.sample.app;

public class Application {

 public static void main(String args[]) {
  String s1 = "Hello World";
  String s2 = "Hello World";
  String s3 = new String("Hello World");

  System.out.println("s1 Reference Address => " + System.identityHashCode(s1));
  System.out.println("s2 Reference Address => " + System.identityHashCode(s2));
  System.out.println("s3 Reference Address => " + System.identityHashCode(s3));

  System.out.println("\n(s1.equals(s2)) : " + (s1.equals(s2)));
  System.out.println("(s1.equals(s3)) : " + (s1.equals(s3)));
 }
}

String intern method
'java.lang.String' class provides intern method, when this method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.


Application.java
package com.sample.app;

public class Application {

 public static void main(String args[]) {
  String s1 = "Hello World";
  String s2 = "Hello World";
  String s3 = new String("Hello World").intern();

  System.out.println("s1 Reference Address => " + System.identityHashCode(s1));
  System.out.println("s2 Reference Address => " + System.identityHashCode(s2));
  System.out.println("s3 Reference Address => " + System.identityHashCode(s3));

  System.out.println("\n(s1==s2) : " + (s1 == s2));
  System.out.println("(s1==s3) : " + (s1 == s3));
  System.out.println("(s2==s3) : " + (s2 == s3));

 }
}


Output
s1 Reference Address => 2018699554
s2 Reference Address => 2018699554
s3 Reference Address => 2018699554

(s1==s2) : true
(s1==s3) : true
(s2==s3) : true

When to use String intern method?
String intern method can be useful, while comparing the string objects for equality.

When you see the equals method of string class, it looks like below. It is compares two strings character by character, whenever the characters are not equals, then this method return false.

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
        

Suppose if a string of size 1K characters, you will end up in comparing all the 1000 characters if the strings are equal. But if we intern the strings and compare via == operator, it checks for reference address, which is more efficient as compared to equals method.

You may like

No comments:

Post a Comment