Mastering Strings in Java

Ahad Arif
8 min readMar 5, 2023

--

Best Practices and Techniques for Effective Programming

What is String?

A String in Java is an object that represents a sequence of characters. In Java, strings are immutable, meaning that once a string object is created, its contents cannot be changed.

How to Create String Objects in Java?

There are two ways to create a String object:

By string literal

String str = ”Yahoo!! I'm inside String Constant Pool(Heap)”;

When a string literal is used to create a String object, the JVM checks if the string already exists in the string pool. If it does, a reference to the existing object is returned instead of creating a new object. This means that two string literals with the same value will refer to the same object in memory, which can save memory and improve performance.

By new keyword

String str = new String("Oh noo!! Im inside non-Pool(Heap) memory");

Using the new keyword to create a String object, however, always creates a new object in the heap, regardless of whether the string already exists in the string pool or not. This can result in unnecessary memory usage and slower performance.

Why String objects are immutable in Java?

  1. ClassLoader

While the immutability of String is not directly tied to the ClassLoader, it does have implications for class loading and the management of class names and constants. For example, class names passed to the ClassLoader are typically represented as strings, and their immutability ensures that the class loading process is stable and consistent.

2. Thread Safe

Immutable objects, including strings, are free from data races when accessed by multiple threads concurrently. A data race occurs when two or more threads concurrently access a shared mutable object, leading to unexpected behavior or incorrect results. Since strings cannot be modified, concurrent access to the same string object is safe.

3. Heap Space

Sharing of immutable strings can significantly reduce memory usage by avoiding the need to create multiple copies of the same string.

Why String class is Final in Java?

The String class in Java is declared as final, which means that it cannot be extended or subclassed. The decision to make the String class final was made for several reasons:

  • Immutable: The String class is designed to be immutable, which means that its internal state cannot be changed after it is created. Making the class final ensures that the internal state of a String object cannot be modified by a subclass or any other code.
  • Security: The final keyword provides an extra layer of security by preventing malicious code from creating a subclass of String and overriding its methods. This is important because String objects are used to represent sensitive information such as passwords and encryption keys.
  • Performance: The String class is heavily used in Java applications, and making it final can improve performance by allowing the compiler to make certain optimizations. For example, the compiler can inline methods and cache hash codes because it knows that the String class cannot be extended or modified at runtime.

In summary, the decision to make the String class final was made for reasons related to immutability, security, and performance. By making the String class final, Java ensures that the internal state of a String object cannot be modified, provides an extra layer of security, and allows for certain optimizations that can improve performance.

How should we compare String in java?

In Java, there are several ways to compare strings:

  1. Using the equals() method: This method compares the contents of the two strings and returns true if they are equal.

2 . Using the compareTo() method: This method compares two strings lexicographically. It returns an integer value that indicates whether the first string is less than, equal to or greater than the second string

3. Using the equalsIgnoreCase() method: This method compares two strings while ignoring the case of the letters in the strings.

4. Using the contentEquals() method: This method compares the contents of two string objects.

5. Using the == operator: This operator compares the object reference of the two strings. It returns true if they are pointing to the same object in memory.

Note that the first four methods compare the contents of the strings, while the last method compares the object references of the strings.

String Concatenate

  1. Using the + operator: This operator can be used to concatenate two or more strings.

which is translated into the following code

Another Example

The compiler performs these operations based on the order of precedence and the data types of the operands.

Java does provide a limited form of operator overloading for built-in types

2. Using the String concat() method

String s1=”Hello “;
String s2="World";
String s3=s1.concat(s2);
System.out.println(s3);//Hello World

3. Using StringBuilder class

StringBuilder s1 = new StringBuilder(“Hello”); //String 1
StringBuilder s2 = new StringBuilder(" World"); //String 2
StringBuilder s = s1.append(s2); //String 3 to store the result
System.out.println(s.toString()); //Displays result

4. Using format() method

String s1 = new String(“Hello”); //String 1
String s2 = new String(" World"); //String 2
String s = String.format("%s%s",s1,s2); //String 3 to store the result
System.out.println(s.toString()); //Displays result

5. Using String.join() method

String s1 = new String(“Hello”); //String 1
String s2 = new String(" World"); //String 2
String s = String.join("",s1,s2); //String 3 to store the result
System.out.println(s.toString()); //Displays result

6. using StringJoiner class

Basic Syntax for creating StringJoiner is

public StringJoiner(
CharSequence delimiter,
CharSequence prefix,
CharSequence suffix
)
StringJoiner s = new StringJoiner(“, “); //StringeJoiner object
s.add("Hello"); //String 1
s.add("World"); //String 2
System.out.println(s.toString()); //Hello, World

7. Using Collectors.joining() method

List<String> strList = Arrays.asList(“abc”, “pqr”, “xyz”); //List of String array
String str = strList.stream().collect(Collectors.joining(", ")); //performs joining operation
System.out.println(str.toString()); // abc, pqr, xyz

Substring in Java

  1. Using subString(startIndex,endIndex);
String s=”hello”;
System.out.println(s.substring(0,2)); //returns he as a substring

Points to be noted here :

startIndex: inclusive | endIndex: exclusive

2. Using Split()

class Main {
public static void main(String[] args) {
String text = "Java is a fun programming language";

// split string from space
String[] result = text.split(" ");


System.out.print("result = ");
for (String str : result) {
System.out.print(str + ", ");
}
}
}

// Output: result = Java, is, a, fun, programming, language,

here,

The syntax of the string split() method is:

string.split(String regex, int limit)

Here, string is an object of the String class.

The string split() method can take two parameters:

  • regex — the string is divided at this regex (can be strings)
  • limit (optional) — controls the number of resulting substrings

If the limit parameter is not passed, split() returns all possible substrings.

Some More Useful methods for String in JAVA

  • contains() checks whether the string contains a substring
  • substring() returns the substring of the string
  • join() join the given strings using the delimiter
  • replace() replaces the specified old character with the specified new character
  • replaceAll() replaces all substrings matching the regex pattern
  • replaceFirst() replace the first matching substring
  • charAt() returns the character present in the specified location
  • getBytes() converts the string to an array of bytes
  • indexOf() returns the position of the specified character in the string
  • compareTo() compares two strings in the dictionary order
  • compareToIgnoreCase() compares two strings ignoring case differences
  • trim() removes any leading and trailing whitespaces
  • format() returns a formatted string
  • split() breaks the string into an array of strings
  • toLowerCase() converts the string to lowercase
  • toUpperCase() converts the string to uppercase
  • valueOf() returns the string representation of the specified argument
  • toCharArray() converts the string to a char array
  • matches() checks whether the string matches the given regex
  • startsWith() checks if the string begins with the given string
  • endsWith() checks if the string ends with the given string
  • isEmpty() checks whether a string is empty of not
  • intern() returns the canonical representation of the string
  • contentEquals() checks whether the string is equal to charSequence
  • hashCode() returns a hash code for the string
  • subSequence() returns a subsequence from the string

StringBuilder / StringBuffer in jAVA

StringBuilder Constructor

  • StringBuilder() It creates an empty String Builder with the initial capacity of 16.
  • StringBuilder(String str) It creates a String Builder with the specified string.
  • StringBuilder(int length) It creates an empty String Builder with the specified capacity as length.

StringBuffer Constructor

  • StringBuffer() It creates an empty String buffer with the initial capacity of 16.
  • StringBuffer(String str) It creates a String buffer with the specified string..
  • StringBuffer(int capacity) It creates an empty String buffer with the specified capacity as length.

Important Methods in StringBuffer and StringBuilder

  • append(String s) It is used to append the specified string with this string. The append() method is overloaded like append(char), append(boolean), append(int), append(float), append(double) etc.
  • insert(int offset, String s) It is used to insert the specified string with this string at the specified position. The insert() method is overloaded like insert(int, char), insert(int, boolean), insert(int, int), insert(int, float), insert(int, double) etc.
  • replace(int startIndex, int endIndex, String str) It is used to replace the string from specified startIndex and endIndex.
  • delete(int startIndex, int endIndex) It is used to delete the string from specified startIndex and endIndex.
  • reverse() is used to reverse the string.
  • int capacity() It is used to return the current capacity.
  • ensureCapacity(int minimumCapacity) It is used to ensure the capacity at least equal to the given minimum.
  • charAt(int index) It is used to return the character at the specified position.
  • length() It is used to return the length of the string i.e. total number of characters.
  • substring(int beginIndex) It is used to return the substring from the specified beginIndex.
  • substring(int beginIndex, int endIndex) It is used to return the substring from the specified beginIndex and endIndex.

Difference Between StringBuilder and StringBuffer

  • StringBuffer is synchronized. Where as StringBuilder is non-synchronized.
  • StringBuffer is less efficient than StringBuilder due to synchronization where as StringBuilder is more efficient than StringBuffer for non-synchronized approach.
  • StringBuffer was introduced in Java 1.0 where asStringBuilder was introduced in Java 1.5

synchronized | thread safe = two threads can call the methods simultaneously.
non-synchronized | not thread safe = two threads can’t call the methods simultaneously.

--

--