Java Strings API - mariamaged/Java-Android-Kotlin GitHub Wiki

Java - Strings

4.1.1 Creating String Objects

You can create objects of the class String by:

  • Using the new operator.
  • Using String literal values (values within double quotes).
  1. Let' create two String objects with the value "Paul" using the operator "new":
String st1 = new String("Paul");
String str2 = new String("Paul");
System.out.println(str1 == str2);
  • Comparing the objects referred to by the variables str1 and str2 prints false.
  • The operator == compares the addresses of the objects referred to by the variables str1 and str2.
  • Even thought these String objects store the same sequence of characters, they refer to separate objects stored at separate locations.
     

enter image description here

  1. Let's initialize two String variables with the value "Harry" using the assignment operator (=):
String str3 = "Harry";
String str4 = "Harry";
System.out.println(str3 == str4);
  • In the case of the variables str3 and str4, the objects are created and stored in a pool of String objects.
  • Before creating a new object in the pool, Java searches for an object with similar contents.
  • When the following line executes, no String object with the value of "Harry" is found in the pool of String objects:
String str3 = "Harry";
  • As a result, Java creates a String object with the value "Harry" in the pool of String objects referred to by the variable str3.
     

enter image description here

  • When the following line of code executes, Java is able to find a String object with the value "Harry" in the pool of String objects:
String str4 = "Harry";
  • Java does not create a new String object in this case, and the variable str4 refers to the existing String object "Harry".
      enter image description here
  1. You can create a String object by enclosing a value within double quotes ("):
System.out.println("Morning");
  • These values are reused from the String constant pool if a matching value is found.
  • If a matching value is not found, the JVM creates a String object with the specified value and places it in the String constant pool.
String morning1 = "Morning";
System.out.println("Morning" == morning1); // Prints true.

enter image description here

  1. You can also invoke other overloaded constructors of the class String to create its objects by using the operator new:
String girl = new String("Shreya"); // Constructor that takes a string.
char[] name = {'P', 'a', 'u', 'l');
String boy = new String(name); // Constructor that takes a char array.
  1. You can also create objects of String using the classes StringBuilder and StringBuffer.
StringBuilder sd1 = new StringBuilder("String Builder");
String str5 = new String(sdl);
StringBuffer sd2 = new StringBuffer("String Buffer");
String str6 = new String(sd2);
Note: Because String is a class, you can assign null to it.
The default value for String is null.

4.1.2 The class String is immutable

  • Once created, the contents of an object of the class String can never be modified.
  • The immutability of String objects helps the JVM reuse String objects,:
    • Reducing memory overhead.
    • Increasing performance.
  • String objects can be shared across multiple reference variables without any fear of changes in their values.
  • If the reference variables str and str2 refer to the same String object value "Java", str1 need not worry for its lifetime that the value "Java" might be changed through the variable str2.
Implementation of String Immutability
  1. The class String stores its values in a private variable of the type char array char[] value.
    • Arrays are fixed in size and don't grow once initialized.
  2. This value variable is marked as final in the class String.
    • Note that final is a nonaccess modifier, and a final variable can be initialized once.
  3. Non of the methods defined in the class String manipulate the individual elements of the array value.
     

enter image description here
  enter image description here
  enter image description here
 

  • The char array used by the class String is marked as private, which means that that is isn't accessible outside the class for modification.
  • The class String itself doesn't modify the value of the variable either.
  • All the methods defined in the class String, such as substring, concat,toLowerCase, toUpperCase,trim, and so on, which seem to modify the content of the String object on which they're called, create and return a new String object rather than modify the existing value.

4.1.3 Methods of the class String

enter image description here

charAt()

You can use the method charAt(int index) to retrieve a character at a specified index of a String:

String name = new String("Paul");
System.out.println(name.charAt(0)); // Prints P.
System.out.println(name.charAt(2)); // Prints a.

enter image description here

  • Because the last character is placed at index 3, the following code will throw an exception at runtime:
System.out.println(name.charAt(4));
  • Runtime exception: is a programming error determined by the Java Runtime Environment (JRE) during the execution of the code.

indexOf()

You can search a String for the occurrence of a char or a String. If the specified char or String is found in the target String, this method returns the first matching position; otherwise, it returns -1.

By default, the indexOf() methods starts its search from the first char of the target String.

If you wish, you can also set the starting position.

String letters = "ABCAB";
System.out.println(letters.indexOf('B')); // Prints 1.
System.out.println(letters.indexOf("S")); // Prints -1.
System.out.println(letters.indexOf("CA")); // Prints 2.
System.out.println(letters.indexOf("B", 2)); // Prints 4.

enter image description here

substring()

  1. The first returns a substring of a String from the position you specify to the end of the String, as in the following example:
String exam = "Oracle";
String sub = exam.substring(2);
System.out.println(sub); // Prints acle.

enter image description here

  1. You can also specify the end position with this method:
String exam = "Oracle";
String result = exam.substring(2, 4);
System.out.println(result); // Prints ac.

enter image description here

  • Here's a simple way to remember this rule:
    • Length of String returned by substring() = end - start.

trim()

The trim() method returns a new String by removing all the leading and trailing white space in a String.

White spaces are blanks (new lines, space, or tabs).

String varWithSpaces = "  AB CB    ";
System.out.print(":");
System.out.print(varWithSpaces); 
System.out.println(":");
// :  AB CB   :
System.out.print(":");
System.out.print(varWithSpaces.trim());
System.out.print(":");
// :AB CB:

replace()

This method will return a new String by replacing all occurrences of a char with another char.

Instead of a char to be replaced by another char, you can also specify a sequence of characters - a String to be replaced by another String.

String letters = "ABCAB";
System.out.println(letters.replace('B', 'b')); // Prints AbCAb
System.out.println(letters.replace("CA", "12")); // Prints AB12AB
  • Notice the type of the method parameters passed on this method: either char or String.
    • You can't miss these parameter types.
String letters = "ABCAB";
System.out.println(letters.replace('B', "b")); // Won't compile.
System.out.println(letters.replace("B", 'b')); // Won't compile.

length()

You can use the length() method to retrieve the length of a String.

System.out.println("Shreya".length()); // Prints 6.

startsWith() and endsWith()

The method startsWith() determines whether a String starts with a specified prefix, specified as a String.

You can also specify whether you wish to search from the start of a String or from a particular position.

This method returns true if a match is found or false otherwise.

String letters = "ABCAB";
System.out.println(letters.startsWith("AB")); // Prints true.
System.out.println(letters.startsWith("a")); // Prints false.
System.out.println(letters.startsWith("A", 3)); // Prints true.

The method endsWith() tests whether a String ends with a particular suffix.

It returns true for a matching value and false otherwise.

System.out.println(letters.endsWith("CAB")); // Prints true.
System.out.println(letters.endsWith("B")); // Prints true.
System.out.println(letters.endsWith("b")); // Prints false.

Method Chaining

It is a common practice to use multiple String methods in a single line of code:

String result = "Sunday ".replace(' ', 'Z').trim().concat("M n");
System.out.println(result); // Prints SundayZZM N
  • These methods are evaluated from left to right.

4.1.4 String objects and Operators

  • Concatenation operators (+ and +=) have a special meaning for Strings.
  • Behind the scenes, string concatenation is implemented by using the StringBuilder or StringBuffer classes.
  • But remember that a string is immutable.
String aString = "OCJA" + "Cert" + "Exam"; // String that contains OCJACertExam.

int num = 10;
int val = 12;
String aStr = "OCJA";
String anotherStr = num + val + aStr;
System.out.println(anotherStr); // Prints 22OCJA not 1012OCJA.
  • The expression (num + val + aStr) is evaluated from left to right.
  • Here's the sequence of steps executed by Java to execute the expression:
    • Add operands num and val to get 22.
    • Concatenate 22 with OCJA to get 220CJA.
  • If you wish to treat the numbers stored in variables num and val as String values, modify the expression as follows:
String anotherStr = "" + num + val + aStr; // Evaluates to 10120CJA.

enter image description here

  • When you use += to concatenate String values, ensure that the variable you are using has been initialized (and does not contain null).
String lang = "Java";
lang += " is everywhere";
String initializedToNull = null;
initializedToNull += "Java";
System.out.println(initializedToNull); // Prints nullJava.

4.1.5 Determining Equality of Strings

  • The correct way to compare two String values for equality is to use the equals() method defined in the String class.
  • This method returns a true value if the object being compared to:
    • Is not null.
    • Is a String object.
    • Represents the same sequence of characters as the object to which it is being compared.

Equals Method

enter image description here
  enter image description here

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

4.2 Mutable Strings: StringBuilder

The class StringBuilder is defined in the package java.lang, and it has a mutable sequence of characters.

  • You should use the class StringBuilder when:
    • You're dealing with larger strings.
    • You're modifying the contents of a string often.
  • Doing so will improve the performance of your code.
  • Unlike StringBuilder, the String class has an immutable sequence of characters.
    • Every time you modify a string that's represented by the String class, your code creates new String objects instead of modifying the existing one.

4.2.1 The StringBuilder class is mutable

  • In contrast to the class String, the class StringBuilder uses a non-final char array to store its value.
  • Following is a partial definition of the class AbstractStringBuilder (the superclass of the class StringBuilder).
  • It includes the declaration of the variables:
    • value which is used to store the value of the string.
    • count which is used to store the length of the string.
        enter image description here

4.2.2 Creating StringBuilder objects

  • You can create objects of the class StringBuilder using multiple overloaded constructors, as follows:
class CreateStringBuilderObjects {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder(sb1);
StringBuilder sb3 = new StringBuilder(50); // Constructor that accepts an int value specifying initial capacity of StringBuilder object.
StringBuilder sb4 = new StringBuilder("Shreya Gupta"); // Constructor that accepts a String.
}
}

enter image description here
 

  1. When you create a StringBuilder object using its default constructor, the following code executes behind the scenes to initialize the array value defined in the StringBuilder itself.
public StringBuilder() {
this.value = new char[16];
}
  1. When you create a StringBuilder by passing it a String, the following code executes behind the scenes to initialize the array value:
public StringBuilder(String str) {
this.value = new char[str.length() + 16];
this.append(str);
}
  1. When you create a StringBuilder by passing it an integer:
public StringBuilder(int x) {
this.value = new char[x];
}

4.2.3 Methods of class StringBuilder

enter image description here

append()

The append method add the specified value at the end of the existing value of a StringBuilder object.

  • Because you may want to add data from multiple data types to a StringBuilder object, this method has been overloaded so that it can accept data of any type.
  1. This method accepts all the primitives, String, char array, and Object, as method parameters, as shown in the following example:
class AppendStringBuilder {
public static void main(String[] args) {
	StringBuilder sb1 = new StringBuilder();
	sb1.append(true); // Appends boolean.
	sb1.append(10); // Appends int.
	sb1.append('a'); // Appends char.
	sb1.append(20.99); // Appends double.
	sb1.append("Hi"); // Appends String.
	System.out.println(sb1); // Prints true10a20.99Hi.
}
}
  1. You can append a complete char array, StringBuilder, or String or its subset as follows:
StringBuilder sb1 = new StringBuidler();
char[] name = {'J', 'a', 'v', 'a', '8'};
sb1.append(name, 1, 3); // Starting with position 1 append 3 characters, position 1 inclusive.
System.out.println(sb1); // Prints ava.
  1. Because the method append also accepts a method parameter of type Object, you can pass it any object from the Java API or your own user-defined object:
class AppendStringBuilder2 {
	public static void main(String[] args) {
		StringBuilder sb1 = new StringBuilder();
		sb1.append("Java");
		sb1.append(new Person("Oracle")); // Append object of class Person.
		System.out.println(sb1);
}
}
class Person {
	String name;
	Person(String str) {this.name = str;}
}
  • The output of the previous code is:
     

enter image description here

  • When you append an object's value to a StringBuilder, the method append calls the static String.valueOf() method.
  • The version taking an Object parameter:
    • Returns the four-letter string "null" if the parameter is null.
    • Otherwise, it calls its toString() method.
    • If the toString() method has been overriden by the class, then the method append adds the String value returned by it to the target StringBuilder object.
    • In the absence of the overriden toString method, the toString() in the class Object executes.
      • For your information, the default implementation of the method toString() in the class Object:
        • Returns the name of the class.
        • Followed by the @char.
        • And unsigned hexadecimal representation of the hashcode of the object (the value returned by the object's hashCode() method).
append implementation
public AbstractStringBuilder append(boolean b) {
	if(b) {
		int newCount = count + 4;
		if(newCount > value.length) expandCapacity(newCount);
		value[count++] = 't';
		value[count++] = 'r';
		value[count++] = 'u';
		value[count++] = 'e';
}
	else {
		int newCount = count + 4;
		if(newCount > value.length) expandCapacity(newCount);
		value[count++] = 'f';
		value[count++] = 'a';
		value[count++] = 'l';
		value[count++] = 's';
		value[count++] = 'e';
}
}

Insert

  • The insert method is as powerful as the append method.
  • It also exists in multiple flavors (read: overloaded method) that accept any data type.
  • The main difference between the append and insert methods is that:
    • The insert method enables you to insert the requested data at a particular position.
    • The append method allows you add the requested data only at the end of the StringBuilder object.
class InsertStringBuilder {
	public static void main(String[] args) {
		StringBuilder sb1 = new StringBuilder("Bon");
		sb1.insert(2, 'r');
		System.out.println(sb1); // Prints Born.
}
}

enter image description here

  1. You can also insert a complete char array, StringBuffer,or String or its subset, as follows:
StringBuilder sb1 = new StringBuilder("123");
char[] name = {'J', 'a', 'v', 'a'};
sb1.insert(1, name, 1, 3);
System.out.println(sb1); // Prints 1ava23.

enter image description here

delete() and deleteCharAt()

The method delete removes the characters in a substring of the specified StringBuilder.

The method deleteCharAt removes the char at the specified position.

class DeleteStringBuilder {
public static void main(String[] args) {
	StringBuilder sb1 = new StringBuilder("0123456");
	sb1.delete(2, 4);
	System.out.println(sb1); // Prints 01456.
}
}

enter image description here

class DeleteStringBuilder {
	public static void main(String[] args) {
		StringBuilder sb1 = new StringBuilder("0123456");
		sb1.deleteCharAt(2);
		System.out.println(sb1); // Prints 013456.
}
}

trim()

Unlike the class String, the class StringBuilder doesn't define the method trim().

An attempt to use it with this class will prevent your code from compiling.

reverse()

As the name suggests, the reverse method reverses the sequence of characters of a StringBuilder.

  • You can't use the method reverse to reverse a substring of StringBuilder.
class ReverseStringBuilder {
	public static void main(String[] args) {
		StringBuilder sb1 = new StringBuilder("0123456");
		sb1.reverse();
		System.out.println(sb1); // Prints 6543210.
}
}

replace()

Unlike the replace method defined in the class String, the replace method in the class StringBuilder replaces a sequence of characters, identified by their positions, with another String, as in the following example:

class ReplaceStringBuilder {
	public static void main(String[] args) {
		StringBuilder sb1 = new StringBuilder("0123456");
		sb1.replace(2, 4, "ABCD");
		System.out.println(sb1); // Prints 01ABCD456.
}
}

enter image description here

subSequence()

Apart from the method substring, you can also use the method subSequence to retrieve a sequence of a StringBuilder object.

  • This method returns objects of type CharSequence.
  • This method does not modify the existing value of a StringBuilder.
class SubSequenceStringBuilder {
	public static void main(String[] args) {
		StringBuilder sb1 = new StringBuilder("0123456");
		System.out.println(sb1.subSequence(2, 4)); // Prints 23.
		System.out.println(sb1); // Prints 0123456.
}
}

A quick note on StringBuffer

  • The classes StringBuffer and StringBuilder offer the same functionality, with one difference:
    • The methods of the class StringBuffer are synchronized where necessary, whereas the methods of the class StringBuilder aren't.
  • When you work with the class StringBuffer, only one thread out of multiple threads can execute your method.
  • This arrangement prevents any inconsistencies in the value of the instance variables that are modified by these (synchronized) methods.
  • But it introduces additional overhead, so working with synchronized methods and the StringBuffer affects the performance of your code.