CommonDocs.org

Strings have been used throughout this series. By now, you should understand that strings hold a series of characters. In this chapter, you will learn more about Strings, how they are structured, how they may be broken down or manipulated, and how to search them. You will also create an algorithm yourself that searches and replaces text in Strings.

At the end of this chapter, you will create a program that counts the number of words in a String.

Structure of Strings

Strings Are Arrays of Characters

Strings are very similar to arrays. You could think of them like an array of characters, where the first index (zero) is the first character in the string. Recall that a String object contains multiple characters and a char object contains a single character. In fact, you may create a String from an array of chars, and explode a String into an array of chars.

Image: Kevin Olson

String from char array

1//Create an array of chars
2char[] arrayOfChars = new char[5];
3arrayOfChars[0] = 'h';
4arrayOfChars[1] = 'e';
5arrayOfChars[2] = 'l';
6arrayOfChars[3] = 'l';
7arrayOfChars[4] = 'o';
8
9//Create a String from an Array of chars
10String myString = new String(arrayOfChars);
11
12//Print it out
13System.out.print(myString);
Terminal
hello

Concatenation

Recall that concatenation is when two or more Strings are combined into one.

1String a = "hello, ";
2String b = "world.";
3String c = a + b;
4System.out.print(c);
Terminal
hello, world.

Substrings

What if you want to extract a section of a String from a larger String? To do this, you may use the .substring(start, end) method. Where start is the index of the String we are starting at, and end is the index we're going up to. The substring will contain the characters between these two indices.

The example below takes a substring of the message "hello, world." It extracts the substring "world" from the larger String.

1String myString = "hello, world.";
2String anotherString = myString.substring(7, 12);
3System.out.println(anotherString);
Terminal
world

Note in the above example, the character at index 7 is 'w' and the character at index 12 is '.' It starts at the first index, and goes up to, but not including the last index. The 'd' in world is actually at index 11, not 12.

Substring Problem

Examine the following code. What arguments go in the second line to produce the word "apple"?

1String myString = "The apple is blue.";
2String substring = myString.substring();
3System.out.println(substring);

String Length

Just as you can get the length of an Array using .length or an ArrayList using .size(), you may find the length of a String using .length().

1//Create a string
2String myString = "Hello! I like ice cream.";
3System.out.printf("The length of this String is: %d", myString.length());
Terminal
The length of this String is: 24

Characters

Recall that characters, using the 'char' datatype, represent a 16 bit Unicode character.

1//create a character "a"
2char character = 'a';
3System.out.println(character);
4
5//increment the value of the char by 1
6character ++;
7//print the result
8System.out.println(character);
Terminal
a
b

Since characters are really just numbers, and the Unicode number for 'a' is 97, when the char above is incremented by 1, it becomes 98. 98 is the Unicode number for the character 'b'.

If you want to find the decimal corresponding to a particular character in Unicode, you may cast the char to an int.

1//create a character "a"
2char character = 'a';
3
4//what's the unicode decimal for this char
5System.out.println((int)character);
Terminal
97

toCharArray

You may use the toCharArray() method on any String to convert it into an array of chars.

1//Create a string
2String test = "Puppies are super cute.";
3
4//Convert it to an array of chars
5char[] charArray = test.toCharArray();
6
7//Print out the first, second, third index of the array
8System.out.println(charArray[0]);
9System.out.println(charArray[1]);
10System.out.println(charArray[2]);
Terminal
P
u
p

Now, you can freely convert Strings to arrays of chars, and arrays of chars back into Strings.

1//Create a string
2String test = "Puppies are super cute.";
3
4//Convert it to an array of chars
5char[] charArray = test.toCharArray();
6
7//Turn it back into another String
8String anotherString = new String(charArray);

When you turn a String into an array of chars, it's said that you are exploding the String.

Case Study: Basic Encryption

Given our knowledge of Strings, Characters, Arrays, and Unicode, we're going to create a program that encrypts and decrypts messages.

How it Works

The program will first ask the user if they want to 1) encrypt or 2) decrypt a message.

If the user opts to encrypt a message, they will be asked to type a message to encrypt. After the message is typed, the user will create a "key" for the encryption. The key will be a number between 1 and 100.

The program will then encrypt the message by incrementing the Unicode value of each character in the string by the key value entered. It will then print out the encrypted message to the console.

If the user opts to decrypt the message, they will paste the encrypted message, enter the key, and the decrypted message will be generated by decreasing the Unicode value of each character in the string entered. Thus recovering the original message.

Tip: Remember to write and test the code yourself. Do not just copy/paste it.

Basic Template

To get started, let's lay out the options and set up the scanner.

1import java.util.Scanner;
2
3public class Main {
4    public static void main(String[] args) {
5
6        //Scanner
7        Scanner input = new Scanner(System.in);
8
9        //User choose option
10        System.out.println("Would you like to:");
11        System.out.println("1) Encrypt a message");
12        System.out.println("2) Decrypt a message");
13
14        int option = input.nextInt();
15		//clear scanner
16        input.nextLine();
17
18        if(option == 1){
19            //TODO Encryption code here
20
21        }
22        else if(option == 2){
23            //TODO Decryption code here
24        }
25
26        input.close();
27        System.out.println("Program ending. Run the program again to encrypt/decrypt a message.");
28
29    }
30
31	 /**
32     *
33     * @param message - the message being encrypted/decrypted
34     * @param key - the number to shift up or down
35     * @return - the encrypted or decrypted message
36     */
37	public static String shiftString(String message, int key){
38		//TODO write a method that shifts each character in the String by a set number
39	}
40}

The Encryption Code

To encrypt the message, we need to ask the user for a message and a key.

1if(option == 1){
2    //Get the message to encrypt
3    System.out.println("Enter a message to encrypt.");
4    String message = input.nextLine();
5
6    //Get an encryption key
7    System.out.println("Please enter a key number between 1 and 100:");
8    System.out.println();
9    int key = input.nextInt();
10    System.out.println("You have selected a key of [" + key + "].");
11
12    //Print out the encrypted message
13    System.out.println("Here is your encrypted message:");
14    System.out.println(shiftString(message, key));
15
16}

The shiftString method will increase each Unicode character by a set number.

The shiftString method

This method converts the message into a char array, increments them by the key, then returns the new String.

1public static String shiftString(String message, int key){
2    //convert the string to an array of chars
3    char[] chars = message.toCharArray();
4    //iterate through the array
5    for(int i = 0; i < chars.length; i++){
6        //increment by the key
7        chars[i] += key;
8    }
9    //convert back to string
10    return new String(chars);
11
12}

Test it

Now, we need to test it. The easiest way to test it is to encrypt a message with a key of "1" which should simply shift the letters up by one.

Terminal
Would you like to:
1) Encrypt a message
2) Decrypt a message
1
Enter a message to encrypt.
hello
Please enter a key number between 1 and 100:

1
You have selected a key of [1].
Here is your encrypted message:
ifmmp

With a key of 1, each letter in "hello" is now the next letter. Char 'i' comes after 'h', 'f' after 'e', 'm' after 'l', and 'p' after 'o'. The Unicode characters have been shifted up once. It's working properly.

Decrypting

Now, we need to write the code to decrypt a message. This will work just like encryption, but instead, we'll use a negative key. This will decrypt the message.

1else if(option == 2){
2    //Get the message to decrypt
3    System.out.println("Paste a message to decrypt.");
4    String message = input.nextLine();
5
6    //Get an encryption key
7    System.out.println("Please enter the key number:");
8    System.out.println();
9    int key = input.nextInt();
10
11    //Print out the decrypted message
12    System.out.println("Here is your decrypted message:");
13    System.out.println(shiftString(message, -key));
14}

Finally, test it out using the key and encrypted message from earlier.

Terminal
Would you like to:
1) Encrypt a message
2) Decrypt a message
2
Paste a message to decrypt.
ifmmp
Please enter the key number:

1
Here is your decrypted message:
hello
Program ending. Run the program again to encrypt/decrypt a message.

Remember: Test your program multiple times with multiple inputs to make sure it's working properly.

Click the button below to view the entire program, if you had any issues.

Case Study: Find & Replace

Another common operation you may need to do with Strings is finding a set of characters. If the characters are found, we can find the index it occurs at or replace it with something else. The String class contains methods you may use to quickly complete these operations, but for demonstration, we'll first look at completing these algorithms from scratch.

Find Example

Look at the following string of text.

1String s = "My very educated mother just served us nine pears.";

Now let's say we want to confirm that the word "nine" exists somewhere in that string. How can we programmatically figure this out?

First, we must iterate through each character in the String and see if an 'n' exists. If it does, we need to see if it's followed by an 'i', then an 'n' and an 'e'. If the first n isn't followed by an 'i', the program should continue searching for another 'n' until it reaches the end of the String.

Create a new project. Add the String to be tested and a method to search it.

1public class Main {
2    public static void main(String[] args) {
3
4        //Test String
5        String s = "My very educated mother just served us nine pears.";
6
7    }
8
9    /**
10     *
11     * @param keyword - the string we are searching for
12     * @param search - the string being searched
13     * @return - true if it was found, false if not
14     */
15    public static boolean keywordExists(String keyword, String search){
16
17        return false;
18    }
19}
Image: Kevin Olson · CC BY-NC-SA

The method that does all the work here is the keywordExists method. It has two parameters - a String containing the keyword we're looking for, and the String being searched. It returns true if the entire keyword was found, and false if not. To find if "nine" exists in String s, it would work like this:

1if(keywordExists("nine",s)){
2    System.out.println("Found 'nine' in String s");
3}

Now, let's implement the keywordExists method.

To begin, we will break both Strings down into arrays of chars. We'll also create a boolean that keeps track of if a match is being found.

1public static boolean keywordExists(String keyword, String search){
2
3        //Break both Strings down into arrays of chars
4        char[] searchArray = search.toCharArray();
5        char[] keywordArray = keyword.toCharArray();
6
7        //keep track of if a match was found
8        boolean foundMatch = false;
9	}
10}

Next, we need to find if the first character in the keyword matches any of the characters in the String being searched. So iterate through each character in the search String, and check if it matches the first character in the keyword String. This loop will run from index 0 of the search String to the last possible index of the search String where an exact match can be found. For example, if I'm searching for the keyword "apple" in the String "Martin has an apple", the last possible index "apple" can start at is 5 spaces from the end. So there's no need to check if there's an 'a' in the last 4 spaces.

1public static boolean keywordExists(String keyword, String search){
2
3        //Break both Strings down into arrays of chars
4        char[] searchArray = search.toCharArray();
5        char[] keywordArray = keyword.toCharArray();
6
7        //keep track of if a match was found
8        boolean foundMatch = false;
9
10        //Iterate through searchArray, up until the last possible point the keyword may exist at.
11        //keywordArray.length is subtracted from searchArray.length, because beyond a certain point keywordArray will no longer fit at the end of searchArray
12        for(int i = 0; i <= searchArray.length - keywordArray.length; i++){
13            //check if this char is the same as the first char we're looking for
14            if(searchArray[i] == keywordArray[0]){
15                //we have found the first character, we must now check if the following characters are equal
16                foundMatch = true;
17            }
18        }
19}

After we find a match of the first character in the keyword, we must see if the following characters in the keyword match the following characters in the String being searched. To do this, we must loop through each following index of the keyword (indices 1 through the end of the array), and check that against each following character in the search String (whatever index the first match was found followed by however many indices are in the keyword array).

If any of these do not match exactly, we know a match has NOT been found and set foundMatch to false. If we get through this entire check, and foundMatch is still true, we know we have found an exact match.

Once an exact match has been found, the entire method returns true. This ends the method and no further checks are performed.

If we get to the end of the search array without finding a single match, then the method returns false at this point.

The completed method looks like this:

1public static boolean keywordExists(String keyword, String search){
2
3        //Break both Strings down into arrays of chars
4        char[] searchArray = search.toCharArray();
5        char[] keywordArray = keyword.toCharArray();
6
7        //keep track of if a match was found
8        boolean foundMatch = false;
9
10        //Iterate through searchArray, up until the last possible point the keyword may exist at.
11        //keywordArray.length is subtracted from searchArray.length, because beyond a certain point keywordArray will no longer fit at the end of searchArray
12        for(int i = 0; i <= searchArray.length - keywordArray.length; i++){
13            //check if this char is the same as the first char we're looking for
14            if(searchArray[i] == keywordArray[0]){
15                //we have found the first character, we must now check if the following characters are equal
16                foundMatch = true;
17                //loop through the following characters in keywordArray
18                for(int x = 1; x < keywordArray.length; x++){
19                    //if the next element in searchArray does not match the next element in keywordArray, it is not a match
20                    if(searchArray[i+x] != keywordArray[x]){
21                        foundMatch = false;
22                        break;
23                    }
24                }
25            }
26            //if we got through all the checks without foundMatch being set to false, we know a complete match has been found and may return true
27            if (foundMatch == true){
28                return true;
29            }
30        }
31        //if we get to this point, we have searched the entire array without finding any exact matches
32        return false;
33    }

Finally, we need to test the method to make sure it works. Create some strings of sentences and select some keywords to search for. The keywords should be taken from the beginning, middle, and end of the search String. This way, we test that the foundMatch method works in multiple locations.

Here is the method I created to test the code.

1public static void main(String[] args) {
2
3    //Test String
4    String s = "My very educated mother just served us nine pears.";
5
6    //Should print true because nine is in the search string
7    System.out.println(keywordExists("nine", s));
8
9    //Should print true
10    System.out.println(keywordExists("pears.", s));
11
12    //Should print false since there is no 'my' only a 'My'
13    System.out.println(keywordExists("my", s));
14
15    //Should print true
16    System.out.println(keywordExists("My", s));
17
18}

Based on the order I called keywordExists, it should print true, true, false, true, in that order.

Terminal
true
true
false
true

The output is what I expected. The method appears to be working properly.

Modify The Code

Directions: Create a new method called firstMatchedIndex, which returns the index at which the first keyword match was found in the String being searched as an int. If no matches were found, it should return "-1". You may do this using the same code as the keywordExists method above, with slight modifications.

Template

1/**
2 * @param keyword - the string we are searching for
3 * @param search - the string being searched
4 * @return - the first index at which a match was found in search string
5 */
6public static int firstMatchedIndex(String keyword, String search){
7
8    //return -1 if no matches were found
9    return -1;
10}

Here is some test code and the expected output once you have successfully implemented the method.

Test Code

1public static void main(String[] args) {
2
3    //Test String
4    String s = "My very educated mother just served us nine pears.";
5
6    //Should return 0, since My starts at index 0 in s
7    System.out.println(firstMatchedIndex("My", s));
8
9    //Should return 3, since "very" begins at index 3 of s
10    System.out.println(firstMatchedIndex("very", s));
11
12    //Should return -1, since this word is not in the search string
13    System.out.println(firstMatchedIndex("father", s));
14
15}
Terminal
0
3
-1

Replace

Now that we've created a method which finds the first occurrence of a shorter String in a longer String, we're going to create a method that replaces the found String with another String.

The method will have three parameters, the keyword we're searching for, the String being searched, and the String we're replacing the keyword with.

1/**
2     *
3     * @param keyword - word we're looking for
4     * @param replace - what it's being replaced with
5     * @param search - the string being searched
6     * @return - the new version of the string being searched
7     */
8    public static String findReplace(String keyword, String replace, String search){
9}

The method will first check if the keyword is in the search String and determine its location using the previously created methods. If nothing was found, there is nothing to replace, and it will just return the original search string.

There are more efficient ways of handling this, but for demonstration, we'll keep things as simple as possible. The contents of the original String will be broken into an array of chars, and a new array of chars will be created which contains just the right amount of space to hold the replacement word. The first section of the original array, up until the first index found of the keyword String, will be copied into the new array. Then, the contents of the "replace" string will be added. Finally, anything coming after the word we're replacing from the original array will be added at the end.

Remember, we're only going to worry about replacing the first instance of the found word.

Once the start, replacement, and end sections have been added to the new char array, we can return it as a String.

Stop: Based on the above explanation, I'd encourage you to try to complete this method by yourself before continuing to read on below.

Get started by checking if the keyword exists. Then, explode the original String and the replacement String.

1public static String findReplace(String keyword, String replace, String search){
2    //make sure there's something to replace
3    if(!keywordExists(keyword, search)){
4        //if the keyword does not exist, return the original String
5        return search;
6    }
7
8    //get the first index
9    int firstIndex = firstMatchedIndex(keyword, search);
10
11    //explode strings
12    char[] originalString = search.toCharArray();
13    char[] replacementWords = replace.toCharArray();

Next, we need to determine how long the new array has to be. For example, if we're searching for the word "hello" and we're replacing it with the word "hey" then the new String has to have 2 elements fewer than the original. If we're searching for the word "dog" and replacing it with the word "wolf," we need to make the new array 1 element larger than the original.

To achieve this, find the difference between the keyword and the replace String. Then create a new array of chars equal to the original array in length, plus or minus the difference.

1int lengthToAdd = 0; //the amount of extra space we need to allocate
2lengthToAdd = replace.length() - keyword.length();
3
4//create a new array, which will eventually become the "replaced" string
5char[] replacementString = new char[originalString.length + lengthToAdd];

Now that we have an empty replacementString ready to hold our new String, we can start adding to it. Create a loop that goes from 0 to the first index we found. This is everything that comes before the replacement. Copy all these values into the new array.

1for(int i = 0; i < firstIndex; i++){
2    replacementString[i] = originalString[i];
3}

Next, insert the replacement word using another loop. It should be added starting at the first index found previously.

1//insert the replacement word
2for(int i = 0; i < replacementWords.length; i++){
3    replacementString[firstIndex + i] = replacementWords[i];
4}

Finally, add the remaining part of the original String. Then return the new String.

1//insert everything that comes after the replaced word
2for(int i = firstIndex + keyword.length(); i< originalString.length; i++) {
3    replacementString[i + lengthToAdd] = originalString[i];
4}
5//return the string
6return new String(replacementString);

Finally, write some test code to the main method make sure it works.

1String s = "My very educated mother just served us nine pears.";
2String x = findReplace("educated", "smart", s);
3
4System.out.println(x);
5
6s = "My very educated mother just served us nine pears.";
7x = findReplace("pears", "pineapples", s);
8
9System.out.println(x);
Terminal
My very smart mother just served us nine pears.
My very educated mother just served us nine pineapples.

For reference, you may access the completed file below.

Built-in Find/Replace Methods

Java has find/replace methods built in. They're more efficient than the methods created above and contain additional functionality. Now that you understand some of the logic behind how they work, use these instead.Find/Replace

1//Test String
2Strings = "My very educated mother just served us nine pears.";
3
4//replace pears with pineapples
5String x = s.replace("pears", "pineapples");
6System.out.println(x);
7
8//replace the first Cow with Cattle
9s = "Cow Chicken Cow Cow Chicken";
10x =  s.replaceFirst("Cow", "Cattle");
11System.out.println(x);
12
13//replaceAll Cow with Cattle
14s = "Cow Chicken Cow Cow Chicken";
15x =  s.replaceAll("Cow", "Cattle");
16System.out.println(x);
Terminal
My very educated mother just served us nine pineapples.
Cattle Chicken Cow Cow Chicken
Cattle Chicken Cattle Cattle Chicken

Other Useful Finder Methods

Below, I summarize some other String search methods you may find useful.

.endsWith()

The .endsWith() method may be used to check if a String ends with a particular set of characters. It returns a boolean (true or false). This may be useful if you're checking for a certain file extension.

1String filename = "c:\users\kevin\desktop\myfile.txt";
2if(filename.endsWith(".txt")){
3    System.out.println("This is a valid text file.");
4}
Terminal
This is a valid text file.

.startsWith()

This works the same as endsWith, except it checks the start of the String.

.contains()

The .contains() method can be used to check if a String contains another String or char. This is like the keywordExists() method we created earlier.

1String aString = "Hello, world.";
2if (aString.contains("w")){
3    System.out.println("There's a w in this String.");
4}
Terminal
There's a w in this String.

indexOf

The .indexOf() method allows you to get the numerical index of the first instance of a located String within a larger String. It works similarly to the firstMatchedIndex method created earlier in this chapter.

1String s = "Hello, World.";
2int indexOfWorld = s.indexOf("World");
3
4//W starts at index 7 of the String, should print 7
5System.out.println(indexOfWorld);
17

The .lastIndexOf() method allows you to get the index of the first character of the last instance of a found String within a larger String.

1String s = "Hello, World. World. World.";
2int indexOfWorld = s.indexOf("World");
3int lastIndexOfWorld = s.lastIndexOf("World");
4System.out.println("The first instance of World is at index " + indexOfWorld + " and the last is at " + lastIndexOfWorld + " in the given String.");
Terminal
The first instance of World is at index 7 and the last is at 21 in the given String.

charAt

The .charAt(idx) method returns the char at a certain index in a String.

1String aString = "Hello, world.";
2char aChar = aString.charAt(4);
3System.out.println("The char at index 4 is: " + aChar);
Terminal
The char at index 4 is: o

Assignment: Word Counter

You have reached the end of this chapter. I hope you've followed along. If you haven't, I'd encourage you to go back and try creating the find/replace algorithms yourself. In the next chapter, you will learn more about object-oriented design.

Word Counter Assignment

Directions: Create a method called getWordCount, which takes a String as a parameter and returns an int. The method checks the given String, counts the amount of words in it, and returns the number of words in the String.

  • Rules
    • The program must only count words (made up of standard 26 letters).
    • The program must work on upper and lower case words.
    • Numbers or symbols by themselves do not count as words.
    • Each word must start and end with a letter.
    • Single character words are permitted.
    • The program does not check spelling. "garbagoo" is counted as a word. The letter "Z" by itself is a word. Any set of alphabetical characters is counted as a word.

Below is a template to get started.

1public class Main {
2    public static void main(String[] args) {
3
4        //Test Code should print 2
5        String a = "Hello, world.";
6        System.out.println(getWordCount(a));
7
8        //should print 5
9        System.out.println(getWordCount("This string has five words."));
10
11        //should print 9
12        System.out.println(getWordCount(" The sound moo is the sound a cow    makes."));
13
14        //should print 7
15        System.out.println(getWordCount("A Z apple! banana a z zebra 12"));
16
17    }
18
19    public static int getWordCount(String s){
20
21        //Your code here
22        return -1;
23    }
24}

Suggested Methodology: Break the String down into an array of chars, iterate through each char with a loop, and check if each char is a letter (upper or lower case). When a letter is found, a word has been found. Count this as one word. Continue until you find something that isn't a letter, then when you find another letter, count it as another word.

Remember, you can get the numerical Unicode value for any char by casting it to an int. Upper case letters have Unicode values from 65 to 90, and lower case from 97 to 122.

It may be helpful to create another method to check if a char is a letter or not. This is up to you.

Up next · part 13 of 17

Chapter 13: Exception Handling - Preventing Errors

In this chapter, you will learn ways to prevent users from unintentionally crashing your programs. The focus will be on try/catch blocks and using specific…

Continue reading
Was this guide useful?

Spotted a mistake? Select the sentence in the guide and choose “Suggest a fix”.

Comments

Found an error? instead, it reaches me faster.

No comments yet. Questions and corrections are welcome.