5

I have a programming homework. It says that I need to reverse the string first, then change it to uppercase and then remove all the whitespaces. I actually did it, but our professor didn't say anything about using replaceAll() method. Is there any other way to do it beside replaceAll()?

Here is my code:

public static void main(String[] args) {
    String line = "the quick brown fox";
    String reverse = "";

    for (int i = line.length() - 1; i >= 0; i--) {
        reverse = reverse + line.charAt(i);
    }
    System.out.println(reverse.toUpperCase().replaceAll("\\s", ""));
}
Community
  • 1
  • 1
NEMES1S
  • 53
  • 4

10 Answers10

4

You can check each character in turn using Character.isWhitespace. Additionally, it is generally better to use a StringBuilder when concatenating inside a loop.

public static void main(String[] args) {
    String line = "the quick brown fox";
    StringBuilder sb = new StringBuilder(line.length());

    for (int i = line.length() - 1; i >= 0; i--) {
        char c = line.charAt(i);
        if(!Character.isWhitespace(c)) sb.append(Character.toUpperCase(c));
    }
    System.out.println(sb);
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
1

@Khelwood's answer as code:

public static void main(String[] args) {
    String line = "the quick brown fox";
    String reverse = "";

    for (int i = line.length() - 1; i >= 0; i--) {
        char currentChar = line.charAt(i);
        if (currentChar != ' ') {
            reverse += currentChar;
        }
    }
    System.out.println(reverse.toUpperCase());

}
1

to strictly follow the professors description (and intentions?):

public static void main(String[] args) {
    String line = "the quick brown fox";

    String reverse = "";
    for (int i = line.length() - 1; i >= 0; i--) {
        reverse = reverse + line.charAt(i);
    }

    String upperCase = reverse.toUpperCase();

    String noSpaces = "";
    for (int i = 0; i < upperCase.length(); i++) {
        char ch = upperCase.charAt(i);
        if (!Character.isWhitespace(ch)) {
            noSpaces = noSpaces + ch;  // or noSpaces += ch;
        }
    }

    System.out.println(noSpaces);
}

Note 1: this can all be done with one loop, but that would not match the description (or no (user)loop at all?).

Note 2: the use of StringBuilder is not needed anymore (when using an actual Java version (>= 11)) - actually I believe it is more efficient not to use it, the compiler does better job (see StringConcatFactory)

Note 3: if allowed to use StringBuilder, it also has a reverse method

Note 4: be aware (for future) that replaceAll() works with regular expression, very powerful, but kind of overkill to just replace a char - replace() would be more moderate

  • `StringConcatFactory` _explicitly_ states that it's for creating concatenators for _a known number of inputs_; use in a loop doesn't match its description. – chrylis -cautiouslyoptimistic- Dec 19 '20 at 22:14
  • @chrylis *known number of inputs* is the case here, or? the code is just concatenating **two** strings - concatenation of above code would be similar to `noSpaces = $concat2(noSpaces, ch);` (method name is not correct, just as example) ((if you don't believe, check generated code with decompiler)) –  Dec 19 '20 at 22:17
  • @chrylis the loop is not eliminated by using the factory, just the (hidden) use of StringBuilder is eliminated - details: [JEP280](http://openjdk.java.net/jeps/280) –  Dec 19 '20 at 22:43
  • The entire point of "use `StringBuilder` in loop" is to avoid creating the new `String` object on every loop iteration. "We're creating all those new objects _slightly faster_" doesn't obviate that. – chrylis -cautiouslyoptimistic- Dec 20 '20 at 02:02
  • @chrylis not 100% correct, the point also was to avoid creating a new SrtingBuilder (and some arrays) each iteration. Not sure how that last comment relates to your first comment, or to my comments... somehow I don't think OP should yet learn about (micro-)optimization It seams more like the teacher wants to teach basics like `for` loop, `if` statement and that... –  Dec 20 '20 at 15:09
  • *For expressions like `a + ":" + b`*, not for loop unrolling. – chrylis -cautiouslyoptimistic- Dec 20 '20 at 20:54
  • @chr sorry, my English is too bad, no idea what you are trying to write now, and it looks like you do not understand (or read) what I wrote - no point in going on with that, –  Dec 20 '20 at 23:13
1

Even without using replaceAll() it’s still a one-liner:

String reverse =
        new StringBuilder(line)
                .reverse()
                .toString()
                .toUpperCase()
                .replace(" ", "");
Community
  • 1
  • 1
Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

Character#isWhitespace

Initialize a StringBuilder object and iterate through each character of the uppercased string. While iterating, use Character#isWhitespace to check if the character is a whitespace character. If not, append the character to the StringBuilder object. After the loop is finished, the StringBuilder object will have all characters except the whitespace characters.

public class Main {
    public static void main(String[] args) {
        String line = "the quick brown fox";
        String reverse = "";

        for (int i = line.length() - 1; i >= 0; i--) {
            reverse = reverse + line.charAt(i);
        }
        String upperCased = reverse.toUpperCase();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < upperCased.length(); i++) {
            char ch = upperCased.charAt(i);
            if (!Character.isWhitespace(ch)) {
                sb.append(ch);
            }
        }

        System.out.println("The given string: " + line);
        System.out.println("The reverse of the given string: " + reverse);
        System.out.println("The reverse of the given string in UPPER case: " + upperCased);
        System.out.println("After removing all space from the reverse of the given string in UPPER case: " + sb);
    }
}

Output:

The given string: the quick brown fox
The reverse of the given string: xof nworb kciuq eht
The reverse of the given string in UPPER case: XOF NWORB KCIUQ EHT
After removing all space from the reverse of the given string in UPPER case: XOFNWORBKCIUQEHT

Note:

  1. If you want to convert sb to a String, use sb.toString().
  2. You can use String instead of StringBuilder but I recommend you use StringBuilder instead of String for such a case because repeated string concatenation in a loop creates additional as many instances of String as the number of concatenation. Check this discussion to learn more about it.
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

Here are two ways. The first uses a standard loop.

String line = "the quick brown fox";
StringBuilder sb = new StringBuilder();
for (int i = line.length() - 1; i >= 0; i--) {
    char ch;
    if ((ch = line.charAt(i)) != ' ') {
        sb.append(Character.toUpperCase(ch));
    }
}
System.out.println(sb.toString());

Prints

XOFNWORBKCIUQEHT

The second makes use of StringBuilder and replaceAll. And regardless, you should ask your professor since nothing was overtly forbidden.

String str = new StringBuilder("the quick brown fox")
        .reverse().toString().replaceAll("\\s+", "").toUpperCase();

System.out.println(str);

Also prints

XOFNWORBKCIUQEHT
WJS
  • 36,363
  • 4
  • 24
  • 39
0

You can use String.codePoints method to iterate over int values of the characters of this string, to reverse their order, change to uppercase and remove whitespaces:

String line = "the quick brown fox";

String reverse = line
        // return IntStream
        .codePoints()
        // return Stream<Character>
        .mapToObj(ch -> (char) ch)
        // reverse the order
        // of characters once
        .sorted((ch1, ch2) -> -1)
        // change to uppercase
        .map(Character::toUpperCase)
        // remove whitespaces
        .filter(ch -> !Character.isWhitespace(ch))
        // return Stream<String>
        .map(String::valueOf)
        // join strings with
        // characters back
        // to a single string
        .collect(Collectors.joining());

System.out.println(reverse); // XOFNWORBKCIUQEHT

See also: Is there a way to reverse specific arrays in a multidimensional array?

0

If you do not need to store the reversed line, you can also just iterate it backwards and print the character immediately.

public static void main(String[] args) {
    String line = "the quick brown fox";
    for (char c : line.toUpperCase().toCharArray()) {
        if (!Character.isWhitespace(c)) {
            System.out.print(c);
        }
    }
}
0

You can iterate over character indices in reverse order, convert them to uppercase and remove spaces as follows:

String str = "the quick brown fox";
String reverse = IntStream
        // iterate over characters in reverse order
        .iterate(str.length() - 1, i -> i >= 0, i -> i - 1)
        // take a character by its index
        .mapToObj(str::charAt)
        // filter only letters
        .filter(Character::isLetter)
        // character to uppercase
        .map(Character::toUpperCase)
        // Stream<String>
        .map(String::valueOf)
        // concatenate into one line
        .collect(Collectors.joining());

// output
System.out.println(reverse); // XOFNWORBKCIUQEHT
0

If the sequence of actions does not matter, then you can first change this string to uppercase, then stream over the character codepoins and filter out whitespaces, and then concatenate back the remaining characters in reverse order:

String line = "the quick brown fox";
String reverse = line
        // upper case String
        .toUpperCase()
        // IntStream over the character code points
        .codePoints()
        // filter out the space characters
        .filter(ch -> !Character.isSpaceChar(ch))
        // Stream<String>
        .mapToObj(Character::toString)
        // concatenate characters in reverse order
        .reduce((a, b) -> b + a)
        .orElse(null);

System.out.println(reverse); // XOFNWORBKCIUQEHT