Transcripted Summary

So, a little bit more about Strings.

Strings we've been using all along, but Strings are not a primitive data type and they are also not a wrapper class.

Strings

A String is an object and it's a sequence of characters. But much like the wrapper classes, the String class provides a lot of helpful methods for dealing with them.

Let's have a look at the Javadoc.



So here we see it says that a String:

String str = "abc";

is equivalent to an array of characters:

char data[] = {'a', 'b', 'c'};
String str = new String(data);

This is what I was saying before, how a String is essentially a sequence of characters. So, you can access a String just like you would an array of characters and each character is an element in an array.

Here are some of the methods available for Strings.



  • A popular one such as charAt() will allow you to get a specific character within the String by its index. This is how you would iterate a String as you would an array. So, you won't be able to use the brackets like we use for other arrays. You would use the charAt() method within a loop, for example. Or if you wanted to get the very first element of the String, you can do a charAt(0).

  • There's also this one, contains(), which is really useful. This will allow you to see if a String contains a certain sequence of characters.

  • equals() we've used before, as well as equalsIgnoresCase().

  • endsWith is a good one if you want to know if something is at the end of a String. There's also startsWith().

  • And then this format() one we've talked about a little bit in previous chapters, where you can use placeholders and then add items back into the String.

  • There's indexOf() where you can pass in some substring of the String and it'll tell you what position it is within the String.

  • isEmpty() can be used if you want to know if this String has data in it or not.

  • length() lets us know how many characters are in the String and we can use this just like we use on the arrays.

  • There's also this matches() one where you can pass in a regular expression and see if the String matches that regular expression.

  • replace() and replaceAll() are useful if there's something within a String that you want to change to something else. You can use these replace methods.

  • split() is also a good one where you have a String and you want to divide it by some delimiter.

  • Here's substring() where you can get part of the String — you can give it a beginning and ending index, and just get that portion of the String.

  • There's a toLowerCase() which is really useful and toUpperCase() as well.

  • trim() is used to get off the white spaces at the beginning or the end of a String.

  • valueOf() lets you pass in any data type and get the String value of it.


To see some of these cool methods in action, let's write a program.



We're going to create a method that counts the number of words in a String and prints them individually on a new line.

I created a new class called TextProcessor and we're just going to make a call to a method that we'll create.

We'll call this countWords and we'll pass it a String.

package chapter8;

public class TextProcessor {

    public static void main(String[] args){
        countWords("I love Test Automation University");
    }
}

Okay, now let's create this method and we'll give it a Javadoc.

/**
* Splits a String into an array by tokenizing it.
* Counts words and prints them
* @param text Full string to be split
*/
public static void countWords(String text){

}

Okay, so we have this text that's been passed in and we want to split this by some delimiter by tokenizing it.

So, what would be something that would indicate that this is a new word in the String? Well we can look at possibly a space.

Let's use the space as the delimiter:

public static void countWords(String text){
    var words = text.split(" ");
}

In the parentheses, you specify what's the delimiter. Our delimiter is a space (between 2 quotation marks). So, we're saying to take this text and split it everywhere we see a space, and that will be stored into words, which is an array of Strings.

Once we have that, we'll need to see how many words there are.

public static void countWords(String text){
    var words = text.split(" ");
    int numberOfWords = words.length;
}

Then we can print this out.

I'm going to use “%d”, which is a placeholder for a number. And then the second argument is what should we replace “%d” with.

String message = String.format("Your text contains %d words:", numberOfWords);
System.out.println(message);

And now we want to print the words out so we can do a for loop.


# TextProcessor.java

package chapter8;

public class TextProcessor {

    public static void main(String[] args){
        countWords("I love Test Automation University");
    }

    /**
     * Splits a String into an array by tokenizing it.
     * Counts words and prints them
     * @param text Full string to be split
     */
    public static void countWords(String text){
        var words = text.split(" ");
        int numberOfWords = words.length;

        String message = String.format("Your text contains %d words:", numberOfWords);
        System.out.println(message);

        for(int i=0; i<numberOfWords; i++){
            System.out.println(words[i]);
        }
    }
}

Let's run it.

And here in the output we see your text contains 5 words and we see each of the 5 words listed.

I

love

Test

Automation

University

Let's look at another example.



We're going to create a method that prints a given String backwards. For example, if given the word “camel”, it prints “lemac”.

Let's make a call to a new method, reverseString() and we'll give it the String, “Hello TAU”. Then we'll create that method.

public static void main(String[] args){
    reverseString("Hello TAU!");
}

/**
* Prints a String in reverse order
* @param text String to reverse
*/
public static void reverseString(String text){

}

So, we're given the String and we want to essentially loop through this String just as we would an array. But this time we want to loop from the back to the front of the String.

Let's create our for loop — we want to start with the last character of this String.

public static void reverseString(String text){

    for(int i=text.length()-1; i>=0; i--){

    }
}

We are using text.length() however, text.length() is going to give us the number of characters, but remember, indexes start at 0. So, we have to say text.length() - 1 and that'll give us the index of the very last character.

We'll use i>=0 for our condition. So that means it's gotten to the beginning of the array by this point. And instead of i++ we are going to use i--.

Inside of the loop, we can simply print out.


# TextProcessor.java

package chapter8;

public class TextProcessor {

    public static void main(String[] args){
        reverseString("Hello TAU!");
    }

    /**
     * Prints a String in reverse order
     * @param text String to reverse
     */
    public static void reverseString(String text){
        for(int i=text.length()-1; i>=0; i--){
            System.out.print(text.charAt(i));
        }
    }
}

Notice we're not going to do println() because we want it all on the same line. So we used print().

We can do our text — and remember I told you, you cannot use the brackets for this, right? While this essentially is an array of characters, it is still an object, so we need to text.charAt() and then give it the index.

So, let's see this one run. Wonderful, and we see “Hello TAU!” is now printed backwards.

!UAT olleH

# StringBuilder Class

The String object is immutable, which means it does not allow for manipulation of the actual String itself. And while there are lots of great methods for Strings, in order to do things like insert or delete characters from a String, you need to use the StringBuilder class.

Let me demonstrate this with an example.



We're going to create a method that adds spaces to a jumbled String, where all words are written together with no spaces, but each new word begins with a capital letter.

So, let's make a call to a new method called addSpaces() and we'll pass it some text, "HeyWorld!It'sMeAngie".

And we'll go ahead and create this method.

public static void main(String[] args){
    addSpaces("HeyWorld!It'sMeAngie");
}

/**
* Adds spaces before each uppercase letter
* @param text jumbled text
*/
public static void addSpaces(String text){

}

I'm going to create a new instantiation of the StringBuilder text and we'll instantiate this to StringBuilder and this takes the text.

public static void addSpaces(String text){

    var modifiedText = new StringBuilder(text);
}

Now let's loop through this.

public static void addSpaces(String text){

    var modifiedText = new StringBuilder(text);

    for(int i=0; i< modifiedText.length(); i++){

    }
}

As we're looking at each character of this String, we want to determine if it is an uppercase. If it is an uppercase, then we need to insert a space into this String.

And as I said, Strings are immutable so we wouldn't be able to do this with just this regular String object of text.

That's why we needed to use the StringBuilder which will allow us to modify a String.

public static void addSpaces(String text){

    var modifiedText = new StringBuilder(text);

    for(int i=0; i< modifiedText.length(); i++){

        if(i!=0 && Character.isUpperCase(modifiedText.charAt(i))){

        }
    }
}

So, I want to say “if i is not equal to zero”, meaning this is not the first letter of the String because we don't want to add a leading space to the beginning of the String — AND (&&) — then I'm going to use the Character wrapper class so that I can use these nice methods available.



I want to use isUppercase() so I can then pass in this specific character by using the charAt(). So, I'm saying if this character is uppercase, then I know to add a space here.

Then I can say, take this modifiedText and insert.

This will take a position, so, the position is i (wherever we are right now), and insert a space.

modifiedText.insert(i, " ");

Once I've gotten here, I want to increment i so that we move past the space that we've just entered and on to the character, which then once it comes back here, will go on to the next character.

modifiedText.insert(i, " ");
i++;

So, by inserting the space, I'm now just moving us past that insertion place.

And then we'll print it out.


# TextProcessor.java

package chapter8;

public class TextProcessor {

    public static void main(String[] args){
        addSpaces("HeyWorld!It'sMeAngie");
    }

    /**
     * Adds spaces before each uppercase letter
     * @param text jumbled text
     */
    public static void addSpaces(String text){

        var modifiedText = new StringBuilder(text);

        for(int i=0; i< modifiedText.length(); i++){
            if(i!=0 && Character.isUpperCase(modifiedText.charAt(i))){
                modifiedText.insert(i, " ");
                i++;
            }
        }

        System.out.println(modifiedText);
    }
}

Let's run it.

Beautiful, so we went from this jumbled String to now something that's readable.

Hey World! It's Me Angie

Here are popular text processing methods from the Character, String and StringBuilder classes.





Optional Independent Exercise

Here's your optional exercise for this chapter. You'll need to verify the strength of a proposed password change.



The password must be at least eight characters long, contain an uppercase letter, contain a special character, not contain the username and not be the same as the old password.

Good luck.

Solution

Programming can be done many different ways, but here’s my solution.



Resources