Java - String, string buffer and string builder

 Java - String, string buffer, and string builder

  1. Difference between string and string buffer (mutability vs mutability and equals() )
  2. String object creation (Heap and SCP)
  3. Importance of string constant pool
  4. The important constructor of string class
  5. Important methods of string class
  6. An important conclusion of string immutability
  7. Possibility of creation of own immutable class
  8. Final vs immutability
  9. The need for string buffer
  10. An important method of string buffer
  11. The important constructor of string buffer
  12. The need of string builder
  13. String buffer vs string builder
  14. String vs string buffer vs string builder
  15. Method chaining 

1. Difference between string and string buffer

  • In software applications most commonly used objects (about 90%) are string objects. 
  • Let's define the String, - The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.
  • Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings. Because String objects are immutable they can be shared. For example:

     String str = "abc";  

is equivalent to:

     char data[] = {'a', 'b', 'c'};     String str = new String(data);

String vs string buffer

  • String objects are immutable (once we declare its value, it can't be changed due to immutable nature) once we create a new object using a new keyword, we can't perform any changes in that object, When we try to change with those changes a new object by default will be created. 
  • There is thirteen String constructor(described below) which allow providing the initial value of the string.
  • Strings are Thread-safe (only one thread at a time), mutable(can be modified) and, the sequence of characters.
  •  A string buffer is like a String, but can be modified. At any point in time, it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls.

Immutablity - It means we can’t change the value of that particular object because of SCP (String Constant Pool a special memory location in Heap, which store those object and its nature is immutable). This nature is because to share same object to multiple times.

package com.company;

class Test {
    public static void main(String[] args) {
        String s = new String("mesanjay");
        s.concat("software");
        System.out.println(s);
    }
}

Output : 

In the above example, String s has an assigned string “mesanjay”. In the next line, we are trying to concat “software”, which means we are trying to modify the object s. But as we know string are immutable therefore, a new object mesanjaysoftware will be created, but this object has no reference hence this is by default available for the garbage collector and our final output will be mesanjay.

mesanjay          // s ---> mesanjay, we can’t modify, when try to change new object will be created
Mesanjaysoftware  //X  eligible for GC, not assigning any reference to s.concat(“software”)
mesanjay           // final output

Ex

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("mesanjay");
        sb.append("software");
        System.out.println(sb);
    }
}

Output : 

In the above example, object sb is StringBuffer type therefor we can easily modify that object and our output will be mesanjaysoftware

mesanjaysoftware    //as we can perform change n string buffer object

String:

ex

package com.company;

class Test {
    public static void main(String[] args) {
        String s1 = new String("mesanjay");
        String s2 = new String("mesanjay");
        System.out.println(s1 == s2);   // == meant for reference/address comparison always     false
        System.out.println(s1.equals(s2)); // true object equals() overridden for content comparision
        //S1 → mesanjay
        //S2 → mesanjay different address hence false
    }
}

StringBuffer:

ex

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb1 = new StringBuffer ("mesanjay");
        StringBuffer sb2 = new StringBuffer ("mesanjay");
        System.out.println(sb1 == sb2);   //  == meant for reference/address comparison always false
        System.out.println(sb1.equals(sb2));   // false
    }
}
  1. Object Class equals() meant for reference/address comparison same as == , applicable for both  string and StringBuffer
  2. String equals() overridden for content comparison. 
  3. StringBuffer equals() not-overridden so works from object class equal() hence work as a reference comparison.

2. String object creation (Heap and SCP)

 String s = new String("mesanjay");     //two object will be created
 String s = "mesanjay";
Heap                        JVMSCP
S -- > mesanjay

S -- > mesanjay   // internal reference maintained by jvm not eligible for GC  

//Till java 1.6 SCP was part of method area PERMGEN,  from Java 1.7v SCP is part of Heap

Ex1

String s1 = new String(“mesnjay”);
String s2 = new String(“mesnjay”);
 
String s1 = “mesanjay”; 
String s2 = “mesanjay”;
HeapSCP

S1 → mesanjay

S2 → mesanjay

mesanjay → reused by s2, s3 s4

Ex2

String s = new String (“me”);
s.concat(“sanju”)
s = s.concat(“sanjay”)
Heap  (runtime operation)SCP

S -- > me

    Mesanju  X eg for GC

S -- > mesanjay

Me

Sanju

sanjay

The output will be as mesanjay

Ex3

String s1 = new String(“String”);
s1.concat(“fall”);
Sring s2 = s1.concat(“winter”);
s2.concat(“summer”)
Sout(s1) // spring
Sut(s2)    //springWinter
heapscp

S1 -- > Spring

Springfall   X gc

S2 → springwinter

springWinterSummer X gc

Spring

Winter

Fall

Summer

3. Importance of SCP

  • A single object can be reused among multiple objects. Therefor performance and memory utilization improve.
  • Immutability in nature, the created object can’t be modified as it may have to reference multiple objects.

SCP is available for string but not for stringbuilder, string is immutable to prevent deletion of reusing same object, All wrapper class object is also immutable.

4. Important constructor of string class

  • String s = new String(); // create an empty string object
  • String s = new String(String literal);   // create object in Heap area
  • String s = new String(StringBuffer sb);   // eqv string to stringBuffer
  • String s = new String(StringBuilder sb)   // eqv string to stringBuilder
  • String s = new String(char[] ch);

Ex   

package com.company;

class Test {
    public static void main(String[] args) {
        char[] ch={'j', 'a', 'v', 'a'};
        String s = new String(ch);
        System.out.println(s);        // java
    }
}

String s = new String(byte[] b); // byte -128 to 127

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        byte[] b = {97, 98, 100};   //97=a, 98=b, 99=c, 100=d Unicode value
        String s = new String(b);
        System.out.println(b);   //abcd
    }
}

5. Important methods of string class

public char charAt(int index);

ex

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "mesanjay"; // count from 0 (zero)
        System.out.println(s.charAt(3));     // a
        System.out.println(s.charAt(30));     // Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 30
    }
}

public String concat(String s);

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "me";
        s = s.concat("sanjay");   // replace  s = s + “sanjay”;  runtime method
        System.out.println(s); // mesanjay
    }
}

public boolean equals(object o);  // content comparison or to check equality of string object

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "MESANJAY";
        System.out.println(s.equals("mesanjay")); // false > content including case
    }
}

public boolean equalsIgnoreCase(object o);  // content comparison or to check equality of string object

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "MESANJAY";
        System.out.println(s.equalsIgnoreCase("mesanjay")); // true > content excluding case
    }
}

public Boolean isEmpty();

ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "";
        System.out.println(s);     // true
        String s1 = "me";
        System.out.println(s1);   // false
    }
}

public Boolean length();  // to check given no of char present

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "sanjay";
        System.out.println(s.length()); // 6   length method,   not for array
        int[] x = {10,20,30};
        System.out.println(x.length); // 3  length variable ,  not for string
    }
}

public String replace(char old, char new); // replace new with old one

Ex

package com.company;

class Test {
    public static void main(String[] args) {
        String s = new String("ababab");
        System.out.println(s.replace('a', 'b'));   //bbbbbb
    }
}

public String substring(int begin);    // return from begin index to end // not write as subString

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "abcdefg";
        System.out.println(s.substring(3)); //defg
    }
}

public String subString(int begin, begin end);   // returns sub string begin index to end -1

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "abcdefg";
        System.out.println(s.substring(3)); //defg
    }
}

public int indexOf(char ch); find character at particular index

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "sanjay";
        System.out.println(s.indexOf('n')); //2      return the index of n
        System.out.println(s.indexOf('l')); //-1     returns -1 when char is not available
        System.out.println(s.indexOf('a')); //1     returns first occurrence of char
    }
}

public int lastIndexOf(char ch); // find the index of last occurrence of char

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "sanjay";
        System.out.println(s.lastIndexOf('n')); //2      return the index of n
        System.out.println(s.lastIndexOf('l')); //-1     returns -1 when char is not available
        System.out.println(s.lastIndexOf('a')); //4     returns first occurrence of char
    }
}

public String toUpperCase();   // return uppercase if not

Ex 

package com.company;

import java.util.Locale;

class Test {
    public static void main(String[] args) {
        String s = "Sanjay";
        System.out.println(s.toUpperCase(Locale.forLanguageTag(s))); //SANJAY
    }
}

public String toLowerCase();   // returns lowercase if not

Ex 

package com.company;

import java.util.Locale;

class Test {
    public static void main(String[] args) {
        String s = "Sanjay";
        System.out.println(s.toLowerCase(Locale.forLanguageTag(s))); //sanjay
    }
}

public String trim(); // returns trimmed char   removes blank space present at begging or end

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        String s = "me sanjay";
        System.out.println(s.trim().length()); //9
    }
}

6. Important conclusion of string immutability

Case 1 :  

  • When we create an object using a new keyword an object is created in the heap area and one object in the SCP area. 
  • In the second line(see the code below), we are modifying the s object using toUpperCase() so there will be one more object in the heap area because we can't modify the first object.
  • In the third line again we are modifying the object using toLowerCase(), but in this case the resultant object is already present in s so s2 also shared the same object.
String s = new String(“sanjay”);
String s1 = s.toUpperCase();
String s2 = s.toLowerCase();
Sout(s == s1);  //false
Sout(s == s2); // true
HeapScp

sanjay  —   > s, s2

SANJAY —   > s1

sanjay

Case 2:

  • In the first-line sanjay object will be created with the s1 reference variable.
  • In the second line, there is no change in content.
  • In the third line also there is no change in content.
  • but in the fourth line, there is change in content, because of running time operation new object is created that object must be created in the heap area.
String s1 = “sanjay”;
String s2 = s1.toString();      // change in content
String s3 = s1.toLowerCase();    // same object is already present
String s4 = s1.toupperCase);
Sout(s1 == s2);   //  true
Sout(s1 == s3);  //true
Sout(s1 == s4);   //false
HeapSCP
SANJAY –--- > S4sanjay   -> s1, s2, s3

7. Possibility of creation of own immutable class

create our own immutable class

package com.company;

final class Test {
    private int i;

    Test(int i) {
        this.i = i;
    }

    public Test modify(int i) {
        if (this.i == i) {
            return this;
        } else {
            return new Test(i);
        }

    }

    public static void main(String[] args) {
        Test t1 = new Test(10);
        Test t2 = t1.modify(100);
        Test t3 = t1.modify(10);
        System.out.println(t1 == t2);  // false
        System.out.println(t1 == t3); //true
    }
}

8. Final  vs immutable

  •  Final related to the reference variable, can’t reassign
  • Immutable related to the object
package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("me");
        sb.append("sanjay");
        System.out.println(sb);   // mesanjay
        sb = new StringBuffer("apple");
        System.out.println(sb); // X CE: can not assign a value to final variable sb
    }
}

9. Need for string buffer

  • If the content is not fixed, keeps on changing frequently, it is better to go for StringBuffer because it will improve the performance and also reduce the memory use altering the existing object.
  • Memory wastage and performance will be down when we use string for frequently changed content.
S  ->  “sanjay”
s.concat(“soft”);
s -> “sanjaysoft”;
s.concat(“ware”);
s-> “sanjaysoftware”;

advantage :

  • All required changes will be performed in existing object only. Only one object will be created. For every small change no, new object will be created

10. Important constructor of string buffer

StringBuffer sb = new StringBuffer();

StringBuffer sb = new StringBuffer(int initialCapacity);

StringBuffer  sb = new StringBuffer(charSequence cs);

StringBuffer sb = new StringBuffer(String s);

String s = new String(“sanjay”);stringBuffer s = new StringBuffer(“sanjay”)
S - > “sanjay”;   // length 6S - > “sanjay”;   // length 6 

StringBuffer sb = new StringBuffer();       //default capacity 16

New capacity = (current capacity +1) * 2 

                                (16+ 1) * 2   =  34

                                (34+1) * 2   =  70

Sb - > // minimum capacity 16 char

Sb - > // minimum capacity 16 char   + 1 char

Ex 

StringBuffer sb = new StringBuffer();

ex

Sout(sb.capacity());   // 16
Sb.append(“abcdefghijklmnop”);
Sout(sb.capacity());   // 16
Sb.append(“q”);
Sout(sb.capacity());  // 34

StringBuffer sb = new StringBuffer(int initialCapacity)

Ex 

StringBuffer sb = new StringBuffer(1000);
Sout(sb.capacity());

 StringBuffer sb = new StringBuffer(String s);

StringBuffer sb = new StringBuffer(“sanjay”);
Sout(sb.capacity);    //   22    --- >16+6

11. Important method of stringBuffer

public int length();

public int capacity();    // total how many char stringBuffer can accommodate.

public char charAt(int index);

Ex   

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("sanjay");
        System.out.println(sb.charAt(3));     // j
        System.out.println(sb.charAt(30));   // Exception in thread "main" java.lang.StringIndexOutOfBoundsException: index 30, length 6
    }
}

public void setCharAt(int index, char newChar);   

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("java");
        sb.setCharAt(0, 'm');  // mava
    }
}

public StringBuffer append(String s);             //boolean, byte, int, float, long  >> overloaded methods

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdefg");
        sb.append("pi value is");
        sb.append("3.14");
        sb.append("it is exactly");
        sb.append(true);
        System.out.println(sb);  // abcdefgpi value is3.14it is exactlytrue
    }
}

public StringBuffer insert(int index, String s);   //boolean, byte, int, float, long  >> overloaded methods

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdefg");
        sb.insert(2, "xyz");    //abxyzcdefg
        sb.append("3.14");
        sb.append("it is exactly");
        sb.append(true);
        System.out.println(sb);  // abxyzcdefg3.14it is exactlytrue
    }
}

public StringBuffer delete(int begin, int end);      // from begin index to end -1 index

ex

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdefg");
        sb.delete(2, 5);
        System.out.println(sb);  //abfg
    }
}

public StringBuffer deleteCharAt(int index);

Ex

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdefg");
        sb.deleteCharAt(3);  
        System.out.println(sb);    //abcefg
    }
}

public StringBuffer reverse();    // only order will be reverse 

Ex

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdefg");
        sb.reverse();
        System.out.println(sb);   //gfedcba
    }
}

public void setLength(int length);     //   set the length, keeps till length rest deletes.

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("abcdefg");
        sb.setLength(3);
        System.out.println(sb);  //abc
    }
}

public void ensureCapacity(int capacity);   //   to increase the capacity based on requirement on fly

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer();
        System.out.println(sb.capacity());      //16
        sb.ensureCapacity(1000);
        System.out.println(sb.capacity());    //1000
    }
}

public StringBuffer trimToSize();   // to deallocate remaining memory

Ex 

package com.company;

class Test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer(1000);
        System.out.println(sb.append("abc"));
        System.out.println(sb.capacity()); //1000
        sb.trimToSize();
        System.out.println(sb.capacity());  // 3
    }
}

12. StringBuilder 

  • A non synchronized version of StringBuffer came in v1.5
  • Need – Due problem with string buffer, In StringBuffer, every method is synchronized, Operate in only one thread at a time, the thread is required to execute one by one,  operation waiting time increases, and performance will be reduced
  • Therefore StringBuilder is introduced, to overcome the problems of stringBuffer, as string builders are synchronized.

To check profile of a class Javap java.lang.stringBuffer

String buffer vs string builder

StringBuffer

StringBuilder  (same  as stringBuffer method)

 

Buffer - > builder

Remove Synchronized

StringBuffer.javaStringBuilder.java

13. String buffer vs string builder

StringBuffer

StringBuilder

Most method synchronizedNo, any method is synchronized
Only one thread at a time (thread safe)Not thread safe
Threads are required to wait to operate on stringBuffer, performance is lowThread do not wait, hence high performanceStringBuilder
stringBuffer v1.0doesstringBuilder v1.5

14. String vs String buffer vs string builder

String

String Buffer

String Builder

If content is fixed (immutable) and thread-safety the required, then it is highly commanded to use stringIf content is not fixed (immutable), the content may change, and thread safety is also a thread-safe major concern(synchronized) then it is highly commanded to use String Buffer.

If content is not fixed, the content may change but thread safety is not a major concern(non-synchronized) then it is highly commanded to use String Builder.

 

15. Method chaining

In most cases almost all method in string in all class return type is the same as method type, there we can add another method in the output of the first one is nothing but method chaining.

sb.m1().m2.m3m4().m5…….

Ex 

package com.company;

class MethodChaining {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("me").append("sanjay").reverse().insert(2, "xyz");     // method execute from left to write.
        System.out.println(sb);  //
    }
}

 

I am trying to cover all the required topics in String, String Buffer,  and String Builder for day to day programming. Keep practicing the general concept of these will make the programming easier when we go for String, String Buffer,  and String Builder. In this blog I am using the technical terms and incomplete sentences with meaningful words only to reduce the verbose, therefore there may be the chance of incomplete sentence and code snippet either. This will make the reader eye-catching to the major points.  Any suggestions and feedback are highly appreciable.

Thank you.

Leave a comment now