HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMajor

Reverse words in a given String

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
wordsstringgivenreverse

Problem

I'd like this code to be improved

Input string: codereview is awesome

Output string: awesome is codereview

My approach:

  • Reverse the entire string



  • Reverse each word in a string



package com.arun.reversewords;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ReverseWords {

public static void main(String[] args) throws IOException {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    System.out.println("Enter the string");
    String s = br.readLine();

    String rev = StringRev(s);

    System.out.println(rev);

}

private static String StringRev(String s) {

    char[] modString = new char[s.length()];

    for (int i = 0; i < s.length(); i++) {
        modString[i] = s.charAt(s.length() - 1 - i);
    }

    s = s.copyValueOf(modString);
    String reverseWord = "";
    String eachWord;
    for (String part : s.split(" ")) {
        eachWord = new StringBuilder(part).reverse().toString();
        reverseWord = reverseWord + eachWord + " ";
    }

    return reverseWord;

  }

}

Solution

There are several problems with your approach:

  • It's strange to reverse the letters, reorder the words, and then reverse the letters again. It's inefficient and unnecessary. You could just reverse the words.



  • The string you return has a trailing space: "awesome is codereview "



  • The naming standard is to use camelCase for methods, which "StringRev" violates, and it's not a good name anyway ("reverseWords" would be better)



  • s for the sentence to reverse is not a good name



It would be more efficient to split by space and then join the words in reverse order. Also keep in mind that String concatenation is not efficient. The efficient way is to use a StringBuilder.

This implementation is more efficient:

public static String reverseWords(String sentence) {
    String[] parts = sentence.split(" ");

    StringBuilder builder = new StringBuilder();
    builder.append(parts[parts.length - 1]);

    for (int i = parts.length - 2; i >= 0; --i) {
        builder.append(" ").append(parts[i]);
    }

    return builder.toString();
}


To verify that the method works correctly, it's good to have unit tests:

@Test
public void testEmptyString() {
    assertEquals("", ReverseWords.reverseWords(""));
}

@Test
public void testWithSingleWord() {
    assertEquals("awesome", ReverseWords.reverseWords("awesome"));
}

@Test
public void testWithTwoWords() {
    assertEquals("is awesome", ReverseWords.reverseWords("awesome is"));
}

@Test
public void testWithSentence() {
    assertEquals("awesome is codereview", ReverseWords.reverseWords("codereview is awesome"));
}


It wasn't part of your specifications, but I would go a bit further and make the solution more robust, by making it work with leading or trailing spaces, and multiple spaces in between words:

public static String reverseWords(String sentence) {
    // trim leading and trailing spaces
    // split on 1 or more spaces between words
    String[] parts = sentence.trim().split("\\s+");
    // ...
}

@Test
public void testWithLeadingSpaces() {
    assertEquals("awesome is codereview", ReverseWords.reverseWords("  codereview is awesome"));
}

@Test
public void testWithMultipleSpaces() {
    assertEquals("awesome is codereview", ReverseWords.reverseWords("codereview   is awesome"));
}


Your program reads a single sentence, reverses the words and prints the output. A BufferedReader can be efficient for processing large inputs, but for such simple uses, a Scanner would be easier and simpler, like this:

public static void main(String[] args) {
    System.out.println("Enter the string");
    Scanner scanner = new Scanner(System.in);
    System.out.println(reverseWords(scanner.nextLine()));
}


With this solution you don't need to declare the method to throw an exception.

For extra user-friendliness, you might want to allow input as command line arguments, and fall back to using System.in only when no arguments were given:

public static void main(String[] args) {
    if (args.length == 0) {
        System.out.println("Enter the string: ");
        Scanner scanner = new Scanner(System.in);
        System.out.println(reverseWords(scanner.nextLine()));
    } else {
        for (String arg : args) {
            System.out.println(reverseWords(arg));
        }
    }
}

Code Snippets

public static String reverseWords(String sentence) {
    String[] parts = sentence.split(" ");

    StringBuilder builder = new StringBuilder();
    builder.append(parts[parts.length - 1]);

    for (int i = parts.length - 2; i >= 0; --i) {
        builder.append(" ").append(parts[i]);
    }

    return builder.toString();
}
@Test
public void testEmptyString() {
    assertEquals("", ReverseWords.reverseWords(""));
}

@Test
public void testWithSingleWord() {
    assertEquals("awesome", ReverseWords.reverseWords("awesome"));
}

@Test
public void testWithTwoWords() {
    assertEquals("is awesome", ReverseWords.reverseWords("awesome is"));
}

@Test
public void testWithSentence() {
    assertEquals("awesome is codereview", ReverseWords.reverseWords("codereview is awesome"));
}
public static String reverseWords(String sentence) {
    // trim leading and trailing spaces
    // split on 1 or more spaces between words
    String[] parts = sentence.trim().split("\\s+");
    // ...
}

@Test
public void testWithLeadingSpaces() {
    assertEquals("awesome is codereview", ReverseWords.reverseWords("  codereview is awesome"));
}

@Test
public void testWithMultipleSpaces() {
    assertEquals("awesome is codereview", ReverseWords.reverseWords("codereview   is awesome"));
}
public static void main(String[] args) {
    System.out.println("Enter the string");
    Scanner scanner = new Scanner(System.in);
    System.out.println(reverseWords(scanner.nextLine()));
}
public static void main(String[] args) {
    if (args.length == 0) {
        System.out.println("Enter the string: ");
        Scanner scanner = new Scanner(System.in);
        System.out.println(reverseWords(scanner.nextLine()));
    } else {
        for (String arg : args) {
            System.out.println(reverseWords(arg));
        }
    }
}

Context

StackExchange Code Review Q#60910, answer score: 20

Revisions (0)

No revisions yet.