Java String Immutable Comparison


Java String Immutable Comparison

Summary: At the end of this tutorial "Java String Immutable Comparison", you will understand the meaning of immutable. Also you will come to know the styles of comparing Java strings.

String handling and string manipulation play a vital role in programming. The simplicity in handling makes a language more programmer-friendly. Java has an in-built support for string handling through String and StringBuffer classes. The predefined methods of these classes make programming easier. Many lengthy codes, generally you write in other languages, may just be forgotten in Java. String handling is an example to prove that Java is production language where you produce more code in less time compared to other languages. Java introduced one more class StringBuilder just to have performance over StringBuffer. All the three classes are placed in java.lang package which is implicitly imported.

Java views string very differently. In Java a string is not an array of characters with a terminating /0. String is a class and using its methods a string can be manipulated. A string literal (value) is to be placed in double quotes.

String str = "Best Wishes";

Best Wishes is known as a string literal and str is the object of String class that points to the location of "Best Wishes".

Following is the class signature of String as defined in java.lang package.

public final class String extends Object implements Serializable, Comparable, CharSequence

Immutable Nature (Read only) with Java String Immutable Comparison

JVM memory allocation is quiet different for strings compared to data types. Whenever a data type literal is reassigned, the value in the memory location (address) changes but not the memory location (that is, in the same address the value is changed). But in case of strings, memory address itself changes. To be more clear, when a string literal is reassigned, the new value is stored in a new location and the old location is garbage collected. That is, a string value cannot be changed in the same location. This is known as immutable nature of strings. Memory management is a big overhead to the operating system. This nature is one of the reasons for the slow execution of Java. The other two are bytecode conversion and AWT heavyweight components; everyone has their own reasons from Java designers. Performance is also an unavoidable feature which the programmer should give maximum importance. Depending on the experience, a programmer may take more or less time to develop the code. But performance is a technique that comes slowly. Java designers made a lot of changes in every JDK version towards performance improvement which is discussed separately in three units.

String Vs. StringBuffer

As discussed earlier, Java includes two classes for string handling.

  1. String
  2. StringBuffer

String nature is immutable but StringBuffer is mutable. That is, when a StringBuffer is reassigned, the new value replaces the old value in the same location. Performance-wise StringBuffer is advocated. If the programmer does not change the value of a string, he should prefer String and when changes frequently as the code demands, prefer StringBuffer. For example, for string concatenation, StringBuffer is preferred to String.

Comparing Strings

Regarding the constructors and methods of String class, a programmer can refer Java API. Let us not waste time on this and let us jump into programming where the methods are explained then and there itself. First and foremost is string comparison. There are three styles here which the programmer should be well aware of when to use what. The styles are

  1. Using logical equals to (==)
  2. Using equals() and equalsIgnoreCase()
  3. Using lexicographical order, compareTo()
equals() vs "=="

Programmer should be very very careful in choosing between equals() and "==", else may land in wrong outputs. The logical equals operator (==) in case of variables, either in Java or C/C++, compares the values stored in the locations (addresses), but in case of strings, the locations itself are compared. To be more clear, the logical equals operator in case of strings compare whether two strings refer the same location or not. If they refer, it evaluates to true, else false. The equals() method, in contrary, compares the values stored in the locations but not the locations itself.

public class ImmutableDemo
{
  public static void main(String args[])
  {
    String s1 = "lord";
    String s2 = "lord";

    String s3 = new String("lord");
    String s4 = new String("lord");

    System.out.println(s1 == s2);          // true
    System.out.println(s3 == s4);          // false    
    
    String s3 = new String("lord");
    String s4 = new String("lord");

    System.out.println(s1.equals(s2));     // true
    System.out.println(s3.equals(s4));     // true
	
    s2 = "world";
    System.out.println(s1 == s2);          // false

    String s5 = "Lord";
    System.out.println(s1.equals(s5));     // false

    System.out.println(s1.equalsIgnoreCase(s5));    // true
    System.out.println(s1.length());                // prints 4
 }
}
Output screen of ImmutableDemo.java

String s1 = "lord";
String s2 = "lord";

In the above two statements, both s1 and s2 value (literal) is the same of lord. Because the values are same, the JRE creates only one location for lord and is referred by both objects s1 and s2. This is done by JRE implicitly to save memory. We know earlier, in Java, the memory is implicitly managed; now further we can say, it is managed very effectively to the optimum level.

System.out.println(s1 == s2);

As s1 and s2 refer the same location, s1 == s2 evaluates to true. s1.equals(s2) returns true as the values of s1 and s2 are same. With equals() method, we do not use the word locations because equals() method compares the values but does not bother about locations whether both strings refer the same location or different locations.

String s3 = new String("lord");
String s4 = new String("lord");

In the above two statements, the JRE allocates different memory locations for
s3 and s4 as programmer requested two diferent locations to allocate with new keyword. Observe, with s1 and s2, no new keyword is used.

System.out.println(s3 == s4);

s3 == s4 returns false as both s3 and s4 refer different locations. But s3.equals(s4) returns true as equals() method compares the values but not locations.

System.out.println(s1.equalsIgnoreCase(s5));

equalsIgnoreCase() method does not bother about the case of the letters (equals() minds the case also). As s1 and s5 refer the same word lord but their case is different, both are evaluated to true.

Many a times, programmer does not bother about the locations; he is advised to go for equals() method and not == operator as sometimes, even if the strings are same, the result may come false.

length() method returns the number of characters existing in the string literal.

Note: It must be noted that equals() method is defined in Object class and is overridden by String class. Object class is the supermost class of all classes of Java and beyond which no Java class exist. But equalsIgnoreCase() is defined in String class itself.

Note: Use length() method with strings to know the number of characters in the string literal and length variable incase of arrays to find the number of elements.

Lexicographical Comparison

Lexicographical order means the natural alphabetical order, the same one the dictionary follows. Here, we use compareTo() method. compareTo() method returns zero if both strings are same. A positive integer number if the string calling the method (ASCII values of characters) is more than the string passed as parameter and a negative integer number if the string calling the method is less than the string passed as parameter.

public   class LexiDemo
{
  public static void main(String args[])
  {
    String str1 = "z";
    String str2 = "a";
    String str3 = "z";

    int x = str1.compareTo(str3);  
    System.out.println("str1.compareTo(str3): " + x);   
				                       // the difference of 112-122 = 0
    int y = str1.compareTo(str2);  
    System.out.println("str1.compareTo(str2): " + y);   
			                               // the difference of z-a, 122-97 = 25
    System.out.println("str2.compareTo(str1): " + str2.compareTo(str1));   
			                               // the difference of a-z, 97-122 = -25
    System.out.println("lord and Lord: " + "the lord".compareTo("the Lord"));   
			                               // the difference of l-L, where mismatch occurs, 108-76 = 32
    System.out.println("ASCII value of z: " + (int) 'z');
    System.out.println("ASCII value of a: " + (int) 'a');
    System.out.println("ASCII value of l: " + (int) 'l');
    System.out.println("ASCII value of L: " + (int) 'L');
  }
}
Output screen of LexiDemo.java

System.out.println("lord and Lord: " + "the lord".compareTo("the Lord"));

In lexicographical evaluation, the two strings, "the lord" and "the Lord" are compared. To start with, the first character in both the strings is taken (it is t) and evaluated and as it is 0, the second character is taken and evaluated and so on until the difference is other than 0. When mismatch occurs, their difference is returned and further evaluation is stopped. The above statement prints 32, the differnce of ASCII values of l and L. Other statements, in the above program, are self-explanatory.

21 thoughts on “Java String Immutable Comparison”

  1. Hi,

    Sir why String is immutable. Sir could you please tell me which is the best institution to learn python at ameerpet. Please let me know. I am kind of lost. Hope you will help me.

    Thanks

    Saj

      1. Thanks for your valueable answer ….sir i have little doubt..
        String s1 =”Ankush”;
        s1= s1.concat(“Sehgal”);
        After these s1 refers a new string “AnkushSehgal” and “Ankush” that is in constant pool has no reference and eligible for garbage collection as you said now is there any way to again get this string “Ankush”.

Leave a Comment

Your email address will not be published.