Strings in Java vs Strings in C++
Overview
A String in Java is an object representing a sequence of characters. Java implements strings as objects and has extensive string-handling capabilities such as compare(), concat(), equals(), split(), length(), etc. The java.lang.String class implements the Serializable, Comparable, and CharSequence interfaces.
A string in C++ is an object of the std::string class implemented in the Standard Template Library (STL). It represents a collection or sequence of various characters. The string class stores the characters as a collection of bytes in contiguous memory locations.
Introduction
Strings in Java and C++ are a sequence of characters. Java implements strings as objects of the String class, which is present in the java.lang package. In Java, strings can be declared as string literals as well using quotes. C++ has two ways of representing strings. The first uses a character array and the second uses objects of std::string class implemented in the Standard Template Library.
What are Java Strings
Java implements strings as objects of the String Class. Strings in Java can be constructed in multiple ways, depending on their use. Each quoted stream of characters is a String literal. String literals are stored in a common pool known as the' String Pool' in Java. This facilitates the sharing of storage for strings with the same contents to save memory. An array of characters works the same as Java strings.
Another way to declare strings in Java is to create objects of the String class using the new operator. Instances of the Java String class are stored in the heap memory.
Strings in Java are immutable, i.e., they cannot be changed once initialized. String objects in Java are cached in the String Constant Pool, and this is one possible reason for making Strings immutable in Java. Strings are also immutable in other ways, such as synchronization, security, caching, etc.
Let us discuss an example to understand the concept of immutability in Java better.
The statement given above creates a string Welcome in the String Pool and assigns it to the reference variable str1. Now, let us create another reference variable, str2.
The str2 variable holds the same reference to Welcome as str1. Now, if we change str2 such that:
It modifies the value of str2. But strings are immutable, right?
- It is important to understand that this operation does not modify the Welcome string in the constant pool.
- Due to this operation, JVM creates a new String literal with the value Welcome Home! and assigns its reference to str2.
- Hence, none of the existing strings are modified; only the reference variables are changed. str2 now points to Welcome Home! instead of Welcome.
- str1 still points to Welcome in the pool. Interestingly, there are now three strings in the string constant pool: Welcome, Welcome Home! and Home!
Now, consider the below statement.
When we change str1 to Hello!, a new object with this value is created, and str1 points to this literal in the String Pool. As we can observe, none of the strings points to Welcome; the garbage collector detects this, and memory is restored.
We use the StringBuffer class when a modifiable string is required. Its objects can be modified and do not require creating a new object. Thus, the StringBuffer class modifies the string in less time complexity than the String class.
Note:
The String and StringBuffer classes are defined in java.lang package.
Strings in Java can be initialized in multiple ways
Creating an object of String class
We create an object of string class using the new keyword.
Syntax:
Example:
Output:
Explanation:
- The above program creates two objects, one in the heap memory and one in the string constant pool, to hold the "Hello" string.
- The reference to the object in the heap memory is assigned to the reference variable s.
Using Double quotes
Strings can also be directly created by writing the stream of characters between double quotes.
Syntax:
Example:
Output:
Explanation:
- Here, a string "Hello" is created in the string constant pool, and its reference is assigned to the variable s.
- In this example, no object is created in the heap memory.
Using character Array
We can initialize a string by passing a character array as a parameter while creating an object of the String class.
Syntax:
We can also specify the character array's offset and the length to convert to a string. If the offset is s and the length is l, the string consists of all the characters in the array from index s to s + l - 1. Throws StringIndexOutOfBoundsException if s + l - 1 is out of bounds.
Syntax:
Example:
Output:
StringIndexOutOfBoundsException Example:
Output:
Using ASCII Characters
We can also create a string using an array of bytes. Again, we pass the byte array as a parameter. We can also mention the starting index(offset) and the number of characters to include(length) from the array.
Syntax:
Example:
Output:
stringObj takes all the bytes and converts and combines them to get a string as ABCDEF. .
Operations on Java Strings
Java has several string methods to concatenate two strings, search for a substring, compare two strings, change the case of letters of a string, etc. Some of the basic operations that can be performed on Java Strings are given below:
Method | Description |
---|---|
str.length() | returns the length of the specified string. |
str1.concat(str2) | Appends str2 to the end of str1. |
str1.equals(str2) | Checks if all the characters of str1 and str2 are equal. If they are equal, it returns true; else it returns false. |
str1.contains(str2) | Returns true if str1 contains str2 as a substring else returns false. |
str.substring(int start) | Returns the substring of str1 from the given start index to the end of the string. |
str.substring(int start, int end) | Returns the substring starting from the start index and ending at the end-1 index. |
str.replace(char oldChar, char newChar) | Returns a new string replacing all occurrences of oldChar with newChar in str. |
str.charAt(int index) | Returns the character present at the specified index in str. |
str1.compareTo(str2) | Compares two strings lexicographically. Returns 0 if both are equal, a negative number if str2 is greater and a positive number if str1 is greater. |
str.trim() | Removes all leading and trailing whitespaces. |
str.toLowerCase() | Converts all the characters of str to lowercase. |
str.toUpperCase() | Converts all the characters of str to uppercase. |
str.valueOf() | Returns the string representation of the specified value. |
str.toCharArray() | Returns character array representation of the given string. |
str1.startsWith(str2) | Returns true if str1 begins with the given string str2 else returns false. |
str1.endsWith(str2) | Returns true if the str1 ends with the given string str2 else returns false. |
str.isEmpty() | Returns true if the string is empty. |
Let us now see an example of performing a few methods mentioned above.
Example:
Output:
Explanation:
- In the example above, str1 and str2 are initialized as Butterfly and Beautiful respectively.
- length() returns the length of the number of characters in the str1 i.e. 9.
- concat() combines str1 and str2 and returns ButterflyBeautiful.
- equals() returns true if str1 and str2 have the same characters, and hence, it returns false.
- contains() returns true as str1 has a substring fly in it.
- substring(3) method returns terfly as this is the substring of str1 from index 3.
- substring(2, 5) returns substring of str1 starting from index 2 to index 4 i.e tte.
- replace() replaces all the t with # in str1.
- compare() compares str1 and str2; since it returns a positive number, this implies str1 is greater than str2 in lexicographical order.
More Examples:
Output:
What are Strings in C++
Strings in C++ represent and work with texts and characters. There are two different ways to represent strings: One is derived from the C language, which uses character arrays to represent strings. The other uses objects of the standard string class, i.e., std::string class, defined in C++ STL.
C-Style Character String
The C-style character string is derived from the C programming language to C++. It is can be thought of as a one-dimensional character array that holds a character sequence and is terminated by the null character \0, which signifies that the string has ended.
To initialize and declare C-Style string using Character Array:
Syntax:
When we create a character array, we can either mention each character separately or enter the stream of characters between double quotes.
For Example:
Output:
Explanation:
- In the example, gm and greet are character arrays of sizes 6 and 25, respectively.
- greet is initialized by creating a character array {'H', 'e', 'l', 'l', 'o', '\0'}. \0 is a null character that denotes the termination of the string. gm is initialized using double quotes.
- It takes null characters implicitly.
What if we don't provide the null character?
In the program above, we explicitly mentioned a null character at the end of the greet array. However, when the size of the array(which is 6 in this case) is greater than the number of characters within curly braces, the C language implicitly fills the remaining places with the null character.
Example:
Now, consider the following case where the number of characters inside the curly braces is equal to the size of the array. In this case, we cannot determine the end point of the greet array, and other characters in contiguous memory blocks can also be counted.
Example:
Output:
Explanation:
- We cannot determine the end of the greet char array.
- Since gm characters are present in contiguous memory locations, they are also assumed to be part of the greet char array.
Since char is a primitive data type, strings in C-Style are derived from characters as an array of characters that can be terminated by a null character \0 or are character sequences enclosed within double quotes.
As we are using an array, its size is supposed to be allocated statically during declaration. The memory to the character array is allocated, and it cannot be modified at runtime. It is faster than the string class as we use a character array for strings.
String Class
The C++ language, in its definition, has a way to represent a stream of characters as an object of a class known as std:: string. The string class is based on the OOPs concept. It enables the user to represent the string as an object of the C++ String class(std::string).
To initialize and declare strings using std::string class:
Syntax:
We create an object of string class. Here, we do not need to mention the size of the string while declaring it.
Example:
Output:
Important Points
Dynamic Memory Allocation
C++ string objects perform automatic allocation and deallocation of memory blocks. The memory management is performed explicitly by constructor methods, assignment operators, and destructors. Thus objects of string class are mutable implying that they can be modified irrespective of the initial size of the string.
For instance, if some string was previously of size 15 while the array's capacity was 22. Now, it is initialized to a new value, which is 40 characters long.
The memory management system will allocate a new memory block of size 40 and capacity equal to or greater than 40. The pointer will point to this new array, and the memory blocked by the old array will be restored.
No Array Decay
Array decay is the loss of dimensions or type of the array, and it occurs when we pass the array by value or as a pointer into a function.
We are using an object of the string class instead of an array, which reduces the threat of array decay compared to C-style strings. Also, as memory allocation is dynamic, it allows manifold operations on strings.
Operations on C++ Strings
Function | Description |
---|---|
strcpy(str1, str2) | Copies all the characters of str2 to str1. Returns a pointer to str1 |
strcat(str1, str2) | Appends str2 at the end of str1. Returns a char pointer pointing to the first character of str1. |
strlen(str1) | Returns the size of str1. |
strcmp(str1, str2) | Compares str1 and str2; if they are equals, it returns 0; if str1 is greater than str2, it returns a positive number else returns a negative number. |
strchr(str1, char) | Returns a pointer pointing to the first appearance of character char in str1 or null if not found. |
strrchr(str1, char) | Returns a pointer pointing to the last appearance of character char in str1 or null if not found. |
strstr(str1, str2) | Returns the pointer pointing to the first appearance of str2 in str1. |
strncat(str1, str2, n) | Appends first n characters of str2 at the end of str1. |
strncpy(str1, str2, n) | Copies first n characters of str2 into str1. |
strset(str1, ch) | Sets all the characters of str1 to ch. |
strnset(str1, ch, n) | Sets first n characters of str1 to ch. |
getline(istream& is string& str) | Takes a stream of characters as input from the user in the object memory. |
str.push_back(ch) | Adds the character ch at the end of str. |
str.pop_back() | Deletes the last character of str. |
str.begin() | An iterator to the beginning of the given string. Do not return anything. |
str.capacity() | Returns the size of the currently allocated space for the string. |
str.resize(n) | Changes the capacity of the string to n. |
str.length() | Returns the length of the string str. |
Example:
Output:
Explanation:
- In the above example str1 and str2 are character arrays with ice and cream as values, respectively.
- strcat() combines str1 and str2 and gives the output as icecream also str1 is concat of both the strings i.e. icecream.
- strlen() returns the number of characters in str2 i.e. 5.
- strcmp() returns a positive number as ice is lexicographically greater than cream.
- strchr() returns all the characters starting from first c in str1.
- strrchr() returns all the characters starting from the last appearance of the character e. Thus, it returns eam.
- strcpy() copies the str1 to str2 and str2 becomes icecream.
More Examples:
Output:
- In the example, we ask for a string and store it in str.
- getline() takes the stream of characters until \0 null is found. It is stored in str.
- push_back() pushes '*' at the end of the str, str becomes Scaler*.
- pop_back() pops the last character from str and str again becomes Scaler.
- length() returns the initialized size of the string; here, it is 10.
- resize() changes the size of the string explicitly, and now the length of the string is 23.
Difference Between Strings in Java vs. Strings in CPP
Java String | std::string class in C++ | C-Style String in C++ |
---|---|---|
String is an object of the String Class. | String is an Object of std::string Class. | String is a character array. |
Strings are immutable, i.e. they cannot be changed once initialized. | Strings are mutable, i.e. they can be changed after initialization. | Strings are immutable as we are using an array to represent them. |
String in Java is slower when modified than StringBuffer class. | C++ string class in STL are implemented slower than Strings declared using character array. | Strings are faster in implementations than the String class of C++. |
Memory allocation is static as strings are immutable. | Memory allocation is dynamic, as we don't have to mention the string size. | Memory allocation is static as the size of the character array is to be mentioned during the declaration. |
Strings values can be changed to any size, irrespective of the size of the old value. | Strings can be modified to any other value. | It can be updated, but the size of the new string should be less than or equal to the size mentioned during the declaration. |
Java doesn't require the size to be mentioned during declaration. | No need to specify the size of the string during declaration. | In C-style C++ string, size is to be mentioned for memory allocation as it uses a character array for string implementation. |
Conclusion
- Strings are a stream of characters and can be represented by a stream of characters between a pair of double inverted commas, as a character array, or as an object of a class.
- Strings in Java are objects of class String in java.lang package.
- Java String operations are slow because of string immutability in Java. Each modification in an existing string object creates a new string object, which increases the time complexity of various operations.
- The StringBuffer class in Java can be used for faster string operations.
- C++ has two implementations of string, one as an object of String class and another as a character array derived from C programming language.
- A string derived from the C language is a character Array; memory allocation is static. It is faster in implementation than the String class. It does not offer many built-in functions to modify the existing string, and strings are immutable as the character array size is pre-defined.
- Dynamic memory allocation for string objects of the std::string class. Efficient memory management and the std::string class provide several methods for manipulating strings.