Reverse words in a given String 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 &lt; 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;

  }

}
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 &gt;= 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));
        }
    }
}