Monday, May 24, 2021

String, StringBuffer and StringBuilder

Difference between String and StringBuffer & StringBuilder

Case 1: immutability example
String :
String s= new String("durga");
s.concat("software");
sout("s");
Output: durga
a new object will be created and the string remains the same.

StringBuffer:
StringBuffer sb=new StringBuffer("durga");
sb.append("software");
sout(sb);
Output: durgasoftware
we can perform any changes as it is mutable.

Difference between equals() and '=='

eg1
String s1=new String("rohi");
String s2=new String("rohi");
sout(s1==s2);  ------------> false
sout(s1.equals(s2)); ---------> true

eg2:
StringBuffer sb1=new StringBuffer("rohi");
StringBuffer sb2=new StringBuffer("rohi");
sout(sb1==sb2);  ------------> false
sout(sb1.equals(sb2)); ---------> false

'==' meant for reference comparison or address comparison.
in String equals() method is overridden for content comparison whereas in Object class equals() method is meant for reference comparison or address comparison.

Objects creation Heap and String Constant Pool

String s= new String("durga");
a new object will be created and stored in Heap and String constant pool. the reference type 's' will be referring to Heap side of object and SCP object will not be garbage collected because it will be referenced by JVM.

String s="durga"
in literal type, SCP is checked if the object exists in pool if no then it is created else if it exists then it will be linked to existing ones.

eg1: determine the number of objects created below
        String s1=new String("durga");
        String s2=new String("durga");
        String s3="durga";
        String s4="durga";


eg2: identify the number of objects created during the below String operations
String s=new String("durga");
s.concat("software");
s=s.concat("solutions");

eg3:
String s1=new String("spring");
s1.concat("fall");
String s2=s1.concat("winter");
s2.concat("summer");
System.out.println(s1);
System.out.println(s2);

Output: spring
             springwinter


eg4:
        String s1=new String("cant change");
        String s2=new String("cant change");
        System.out.println(s1==s2);   -------> false
        String s3="cant change";
        System.out.println(s1==s3);   -------> false
        String s4="cant change";
        System.out.println(s3==s4);    -------> true
        String s5="cant "+"change";    ---------> no objects are created(compile time operation) .
        System.out.println(s4==s5);    ---------> true 
        String s6="cant ";  --------> new object created in SCP
        String s7=s6+"change";  ---> new object is created at heap
        System.out.println(s4==s7);    --------> False
        final String s8="cant ";   // final is replaced during compile time 
        String s9=s8+"change";  // assigned to esisting one in compiler during compile time
        System.out.println(s4==s9);  // true

if both strings which are to be added are constants the that operation happens during compile time only. if at least one variable then it will be taken during run time.

advantages of SCP.

scenario 1: in the voters' list if the city name is common then all the crores of the memory location are saved as we can point to a single city string for all the crores of values from the list. to avoid manipulation of the value the strings are immutable.

Important FAQs

1) why the SCP concept is available only for String and not for StringBuffer?
-- String is most commonly used and hence it requires memory management whereas StringBuffer is rarely used hence special memory management is not widely required.

2) Why String objects are immutable and StringBuffer not?
-- because in String we have SCP, i.e we use multiple references to the same object. if we are allowed to change through one reference then we will lose the data hence immutability helps.

3) along with String is there any immutable classes in java?
-- all wrapper class objects eg: Byte,Integer,Long etc.

Constructors of String class

String s=new String();

 String s=new String("string literal");

String s=new String(StringBuffer sb);

String s=new String(StringBuilder sb);

String s=new String(char[] ch);
 char[] c={'j','a','v','a'};
 String s=new String(c);
 sout(s); ---------> java

Strins s=new String(byte[] b);
 byte[] b={97,98,99,100}
 String s=new String(b);
 sout(s);  -----> abcd

Important methods of String class

public boolean isEmpty(); ---> returns true is string is empty

public int length(); ----> returns length of a string
length is different than length()

public String replace(char old, char new); ---->  replaces all the old character with a new character.

public String substring(int begin)  -----> it returns a substring from the begin point mentioned till the end.  (the method is not in camelcase i.e substring and not subString() )

public String substring(int begin,int end) --> return the substring from begin index to end-1.

public int indexOf(char c) ---> returns first available occurence of the index returns '-1' if character not available

public int lastIndexOf(char c)  ----> returns last occurence of  character c.

public String toLowerCase()  

public String toUpperCase() 

conclusion

example1:
String s1=new String("durga");
String s2=s1.toUpperCase();
String s3=s1.toLowerCase();
System.out.println(s1==s2); -------> false
System.out.println(s1==s3); ---> true , as there is no change it is retained.
existing object is reused if there is no change in operation.

example 2:
String s1="durga";
String s2=s1.toString(); ----> pointing to same object as there is no change
String s3=s1.toLowerCase(); --> pointing to same as there is no change
String s4=s1.toUpperCase();
System.out.println(s1==s2); ----> true
System.out.println(s1==s3); ----> true
System.out.println(s1==s4); ----> false
create your own immutable class

eg:
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
 }

final vs immutable

final StringBuffer sb=new StringBuffer("rohi");
sb.append("hi");
System.out.println(sb); ---> returns appended value
sb=new StringBuffer("abc"); ---> Error:cannot assign a value to final variable sb

which of the following is meaningful?
1) final variable  -- true
2) final object -- false
3) Immutable variable -- false
4) immutable object -- true

[Note: it is not possible to make StringBuffer immutable by just making it final. In order to make StringBuffer immutable, we need to modify all its methods which is meaningless.]

StringBuffer(1.0Ver)

If the content value is never fixed then it is recommended to use StringBuffer instead of String. for every manipulation new object is not created in StringBuffer, unlike String. 

In StringBuffer there exists capacity. 16 is the default initial capacity and if filled it will be replaced with a new object with a new capacity i.e (prev capacity+1)*2. 
initially 16
next , (16+1)*2 =34
next (34+1)*2 =70
eg:


Constructors

1) StringBuffer sb=new StringBuffer();
        eg: sb.capacity() ---> 16
               sb.append("1234567890123456");
              sb.capacity() ---> 16
              sb.append("7");
              sb.capacity() ---> 34
              sb.append("123456789012345678");
              sb.capacity() ---> 70

2) StringBuffer sb=new StringBuffer(int initialcapacity); 

3) StringBuffer sb=new StringBuffer(String s);
    eg:
         StringBuffer sb=new StringBuffer("rohi");
          sb.capacity() ---> 20 (capacity=s.length() +16)

Methods of StringBuffer

1) public int length()

2) public int capacity()

3) public char charAt(index)
    eg: StringBuffer sb=new StringBuffer("abcde");
          sout(sb.charAt(3)); --->  d
          sout(sb.charAt(30));  --> String index out of bounds exception

4) public void setCharAt(int index, char new char)

5) append(string s)
    append(Byte[] b)
    append(int i)
    append(long l) ...

6) public StringBuffer insert(int index, String s)
    public StringBuffer insert(int index, double d)
    public StringBuffer insert(int index, boolean b)
    public StringBuffer insert(int index, char ch)

7) public StringBuffer delete(int begin, int end)

8) public StringBuffer deleteCharAt(int index)

9)public StringBuffer reverse()

10) public void setLength(int length);
       eg: StringBuffer sb=new StringBuffer("romy");
             sb.setLength(2) 
              sout(sb);  ---> ro
11)  public void ensureCapacity(itn capacity) --> to increase capacity dynamically after creation
        eg: StringBuffer sb=new StringBuffer();
              sb.capacity() --> 16
              sb.ensureCapacity(1000) --> changing capacity now
              sb.capacity() ---> 1000

12) public void trimToSize();
        eg: StringBuffer sb=new StringBuffer();
              sb.capacity() --> 16
              sb.ensureCapacity(1000) --> changing capacity now
              sb.trimToSize(30);
              sb.capacity()  --->  30
note: every method belonging to StringBuffer class is synchronised hence at a time only one thread is allowed to run.

StringBuilder(1.5Ver)

for a Multithreaded environment, StringBuffer is not recommended hence we go for StringBuilder introduced in 1.5V
all the methods and constructors are the same as StringBuffer. StringBuilder is a non-synchronized version of StringBuffer.

String vs StringBuffer vs StringBuilder

1) String: if the content is fixed and won't change frequently then we should go for String 

2) StringBuffer:  if contents keep changing and moreover if we need thread safety then we should go for StringBuffer.

3) StringBuilder:  if contents keep changing and moreover if we don't need thread safety then we should go for StringBuilder.

Note: all immutable objects in java are Thread-safe as nobody is allowed to perform the modification.

Method Chaining

method chaining is a chain of methods.
StringBuffer sb=new StringBuffer();
sb.append("romy").append("hi").reverse().insert(3,3.145);

No comments:

Post a Comment

SOLID principles in java

SOLID  Single responsibility principle : a class should have only  reason to change, i.e. a class should have only one responsibility/single...