Everything you need to know about "Strings" in Java

Everything you need to know about "Strings" in Java

Overview

  1. Introduction

  2. Creating a String

  3. Operations on Strings

  4. StringBuffer & StringBuilder

  5. Top 10 Problems on Strings


Introduction

A String is nothing but just a sequence of characters. A Character may be an alphabet, a digit or any other character.

Strings in Java are reference-type objects, that are immutable. An immutable object cannot be changed once it has been declared. In Java, Strings should be surrounded by "double quotes".


Creating a String

There are 2 ways to create a string in Java.

  • String literal

  • String Object

String literal

String str = "Hello World";

In the above statement, we have created a String called ‘str’ with the value “Hello World” in it. While evaluating this statement, Java would first evaluate the right part of the statement and creates a String literal with the value “Hello World”. This string literal is created in a special place in heap memory that is known as the “String Constant Pool” or SCP. Once it has created the string literal, then it will create a variable with the name str in the stack memory that will hold the address of the newly created string literal.

Let's say, If we create another string with the same value,

String anotherStr = "Hello World";

Since the string “Hello World” already exists in the string constant pool, Java would not create another string literal, but will directly create a variable named “anotherStr” that would point to the same String literal. This is done for effective memory utilization.

If we were to compare Strings using the equality operator str == anotherStr then, it would return us true, Since both the strings are holding the same memory address.

Note - It is not a correct way to check the equality of strings using the equality operator.

String Object

String str = new String("Hello World");

Same as before, Java would evaluate the right part of the statement and would create a String object inside the heap memory with the value “Hello World”. After the creation of a string object, It would create a variable named str in the stack memory that would point to the string object.

Let's say, If we create another string with the same value,

String anotherStr = new String("Hello World");

Unlike String literal, if we would create another string object with the same value, then Java would create another string object which will get referenced by the “anotherStr” variable.

Here, If we were to compare Strings using the equality operator str == anotherStr then, it would return false. Since both variables are holding different memory addresses.

Multi-line Strings

To create multi-line strings we can use triple double quotes. In the below code, we have created a multi-line string.

String str = """
               This is
               a multi-line String
               example""";

Operations on Strings

Since Strings are immutable, No operations on them would modify the original string but would rather return the modified string.

Concatenating Strings.

We can concatenate String using any of the below ways

String str = "The Quick Brown ";
String anotherStr = "Quick Fox";
System.out.println(str + " " + anotherStr);
System.out.println(str.concat(" ".concat(anotherStr)));
System.out.printf("%s %s", str, anotherStr);

// All of them will provide the same output
The Quick Brown Quick Fox

Another way to concatenate strings is using StringBuilder or StringBuffer

Converting to UPPERCASE or lowercase.

MethodsDescription
str.toLowerCase()Converts a string into lowercase
str.toUpperCase()Converts a string into UPPERCASE
String str = "This is a String";
System.out.println(str.toUpperCase());         // THIS IS A STRING
System.out.println(str.toLowerCase());        // this is a string

Validation on Strings.

MethodDescription
str.startsWith(String s)Returns true if the string str starts with the string s
str.endsWith(String s)Returns true if the string str ends with the string s
str.contains(String s)Returns true if the string str contains the string s
str.isBlank()Returns true if the string str is blank
str.isEmpty()Returns true if the string str is empty
String str = "The Quick Brown Quick";
System.out.println(str.startsWith("The"));         // true
System.out.println(str.startsWith("Quick", 5));    // false
System.out.println(str.endsWith("Quick"));         // true
System.out.println(str.contains("Quick"));         // true

In startsWith() we can optionally provide an int offset to skip the offset number of chars from the start.

String emptyStr = "";
String blankStr = " ";

System.out.println(emptyStr.isBlank());    // true
System.out.println(emptyStr.isEmpty());    // true

System.out.println(blankStr.isBlank());    // true
System.out.println(blankStr.isEmpty());    // false

Locating a Character by its index.

str.charAt(5) - Returns a character that is at the index 5 in the string str.

If the index provided is negative or larger than the string size then this method would throw a StringIndexOutOfBoundsException.

String str = "The Quick Brown Fox";
System.out.println(str.charAt(4));      // Q

Finding the occurrence of a Char or String.

MethodDescription
str.indexOf(String s)Returns the index of the first occurrence of a String s
str.indexOf(Char ch)Returns the index of the first occurrence of a Char ch
str.lastIndexOf(String s)Returns the index of the last occurrence of a String s
str.lastIndexOf(Char s)Returns the index of the last occurrence of a character ch

In case of indexOf() we can also provide an int fromIndex as a 2nd parameter. If provided Java would start the search from the fromIndex. If not provided the default value would be 0.

Similarly, lastIndexOf() can also have an int fromIndex as a 2nd parameter, but here fromIndex is the index counted from the end of the String. If not provided the default value would be the length of the string.

Refer above diagram to understand the below code

String str = "The Quick Brown Quick";

System.out.println(str.indexOf('Q'));           // 4
System.out.println(str.indexOf("Quick"));       // 4
System.out.println(str.indexOf('Q', 5));        // 16
System.out.println(str.indexOf("Quick", 5));    // 16

System.out.println(str.lastIndexOf('Q'));              // 16
System.out.println(str.lastIndexOf("Quick"));          // 16
System.out.println(str.lastIndexOf('B', 12));          // 10
System.out.println(str.lastIndexOf("Quick", 12));      // 4

Splitting a String

str.split(String regex) - Returns an array of Strings after splitting them based on the regex pattern

String str = "The Quick Brown Quick";
String[] spilittedString = str.split(" ");
System.out.println(Arrays.toString(spilittedString));
// Output - 
[The, Quick, Brown, Quick]

Replacing or Extracting a Substring.

MethodDescription
str.replace(CharSequence target, CharSequence replacement)Returns a string after replacing the target with the replacement String
str.replaceAll(String regex, String replacement)Replace all the string that matches the pattern regex with the replacement String
str.substring(int beginIndex)Returns a substring starting from the beginIndex
String str = "The Quick Brown Quick";

System.out.println(str.replace("Quick", "Brown"));
System.out.println(str.replaceAll("[a-z]", "*"));
// Replace all small case letters with *
System.out.println(str.replaceFirst("Quick", "Brown"));

System.out.println(str.substring(0, 10)); 
System.out.println(str.substring(10)); 

// Output
The Brown Brown Brown
T** Q**** B**** Q****
The Brown Brown Quick
The Quick
Brown Quick

Removing trailing & leading spaces.

MethodsDescription
str.trim()Removes all the leading and trailing spaces
str.strip()Removes all the leading and trailing spaces. A newer method that takes into account different kinds of white spaces.
str.stripLeading()Removes all the leading spaces
str.stripTrailing()Removes all the trailing spaces
str.stripIndent()Shifts a multi-line string to the leftmost possible position
String str = "    Hello World!   ";
System.out.println(str.strip());            // Hello World!
System.out.println(str.trim());             // Hello World!
System.out.println(str.stripLeading());     // Hello World!  
System.out.println(str.stripTrailing());    //     Hello World!

The output of the methods is written next to them in a comment.

strip() vs trim()

strip() is a newer method that considers all kinds of white spaces. \u2000 is a kind of white space in Unicode encoding

String str = "\u2000\u2000\u2000Hello World";
System.out.println(str);            //    Hello World
System.out.println(str.trim());     //    Hello World
System.out.println(str.strip());    // Hello World

Comparing String

str.compareTo(anotherStr)

Returns
1. Negative if str < anotherStr
2. Positive if str > anotherStr
3. 0 if str = anotherStr

str.equals(anotherStr)

Returns true if str = anotherStr

str.contentEquals(anotherStr)

Returns true if str = anotherStr

The difference between equals() and contentEquals() is that equals() would only accept Strings whereas contentEquals() is more flexible and can take StringBuffer or CharSequence

String str = "ABC";
String anotherStr = "XYZ";
System.out.println(str.compareTo(anotherStr));   //-23
System.out.println(str.compareTo(str));         // 0
System.out.println(anotherStr.compareTo(str));  // 23
String str = "The Quick Brown Quick";
String anotherStr = "The Quick Brown Quick";
System.out.println(str.equals(anotherStr));           // true
System.out.println(str.contentEquals(anotherStr));    // true

StringBuffer & StringBuilder

Strings are immutable and fixed in size. To create a mutable and growable string we can use StringBuilder & StringBuffer Class.

StringBuffer stringBuffer = new StringBuffer("The ");
stringBuffer.append("Quick ")
            .append("Brown ")
            .append("Fox");
System.out.println(stringBuffer);
StringBuilder stringBuilder = new StringBuilder("The ");
stringBuilder.append("Quick ")
             .append("Brown ")
             .append("Fox");
System.out.println(stringBuilder);

Instead of supplying a String while creating a StringBuilder/StringBuffer object, we can also supply the initial capacity of the string that we are planning to create. StringBuilder stringBuilder = new StringBuilder(10);

Same as Strings we have many methods declared on them. One of the methods to know about is stringBuilder.reverse(). This would reverse the entire String.

StringBuilder stringBuilder = new StringBuilder("Quick Brown Fox");
System.out.println(stringBuilder.reverse());
// Output
xoF nworB kciuQ

StringBuffer vs StringBuilder

At first, we only had StringBuffer Class to create growable Strings. StringBuffer is a thread-safe & synchronized class and hence it requires some extra validation that reduces its performance and makes it slower. StringBuilder Class was introduced as a non-thread-safe and non-synchronized class making it faster than the StringBuffer class.

In conclusion,

  1. StringBuffer - Thread-safe, synchronized but slower

  2. StringBuilder - Not thread-safe, not synchronized but faster


Top 10 Problems on Strings

  1. [Easy] - Longest Common Prefix in an Array

  2. [Easy] - Anagram

  3. [Basic] - Uncommon characters

  4. [Basic] - Find the first repeated character

  5. [Easy] - Reverse words in a given string

  6. [Easy] - Parenthesis Checker

  7. [Medium] - atoi

  8. [Medium] - Form a palindrome

  9. [Medium] - Longest Common Substring

  10. [Medium] - Longest Palindrome in a String