Sign up ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Given a dot separated domain name, reverse the domain elements.

Example:

codereview.stackexchange.com -> com.stackexchange.codereview
google.com -> com.google

I just wanted some suggestions to improve my code. Or if you can suggest a better way, please do so.

package practice;

import java.util.Scanner;
import java.util.StringTokenizer;


public class ReverseDomainName
{
    public static void main(String args[])
    {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter the domain name to be reversed");
        String domain = sc.nextLine();
        sc.close();
        ReverseDomainName obj = new ReverseDomainName();
        String reversedDomainName = obj.reverseDomainNameString(domain);
        System.out.println("The reversed Domain Name = "+reversedDomainName);
    }

    public String reverseDomainNameString(String s)
    {
        String reverse1 = "",word ="" ;
        int i;

        StringTokenizer st = new StringTokenizer(s,"."); 
        int len = st.countTokens();

        /*
         * The check is performed so that instead of com.stackexchange.codereview.
         * we can get the proper com.stackexhange.codereview  so no
         * extra dot
         */

        word  = st.nextToken();
        reverse1 = word+reverse1;


        for(i=1;i<len;i++)
        {
            word = st.nextToken();
            reverse1 = word +"."+reverse1;

        }

        return reverse1;
    }

}
share|improve this question

2 Answers 2

up vote 10 down vote accepted

StringTokenizer is an OK solution, but I think that String.split() would lead to a less verbose solution.

Here is a Java 8 solution that uses split():

public static String reverseDomainNameString(String s) {
    List<String> components = Arrays.asList(s.split("\\."));
    Collections.reverse(components);
    return String.join(".", components.toArray(new String[0]));
}

Without Java 8's String.join(), though, the solution would be more tedious. Note that it might be a good idea to ensure that the string is non-empty, otherwise components[0] (or st.nextToken() in your original solution) would crash.

public static String reverse(String s) {
    if (s == null || s.isEmpty()) return s;
    String[] components = s.split("\\.");
    StringBuilder result = new StringBuilder(s.length());
    for (int i = components.length - 1; i > 0; i--) {
        result.append(components[i]).append(".");
    }
    return result.append(components[0]).toString();
}
share|improve this answer

One big point

From the JavaDoc for StringTokenizer

StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code.1 (emphasis mine)

If even Oracle discourage its use, I suggest you avoid it like the plague.

A Java 8 Stream based solution:

import static java.util.stream.Collectors.joining;

public static String reverseDomain(final String domain) {
    final String[] tokenized = domain.split("\\.");
    return IntStream.range(0, tokenized.length)
            .map(i -> tokenized.length - 1 - i)
            .mapToObj(i -> tokenized[i])
            .collect(joining("."));
}

Here we use String.split to tokenize the String. Using Pattern.splitToStream, which snazzier, makes for uglier code as there is no way to reverse a Stream.

We then Stream the range [0, tokenized.length) and use map to get the indices in reverse. Finally we just need to get the item at the index from tokenized and use Collectors.joining to reconstruct the reverse domain.

As always, unit tests are a must:

@RunWith(Parameterized.class)
public class AppTest {

    @Parameterized.Parameters(name = "{0}")
    public static Collection<Object[]> parameters() {
        return Arrays.asList(new Object[][]{
                {"", ""},
                {"google.com", "com.google"},
                {"codereview.stackexchange.com", "com.stackexchange.codereview"}
        });
    }

    private final String input;
    private final String expected;


    public AppTest(String input, String expected) {
        this.input = input;
        this.expected = expected;
    }


    @Test
    public void testReverseDomain() {
        Assert.assertEquals(expected, App.reverseDomain(input));
    }

}
share|improve this answer
    
Good catch about that remark in the JavaDoc. Interestingly, it's "discouraged", but not quite deprecated. And to my knowledge, no deprecated method has actually been removed, to date. I think it's just saying that the Enumeration-based interface feels "old". – 200_success 13 hours ago
    
Some people still swear by StringTokenizer because it does not use regex to parse the String. Sure, it's not really recommended in this day and age, and choosing a 'discouraged' class in the name of performance smells of premature optimization, but it's still a valid point. Also, I don't think there's an easy equivalent of StringTokenizer.nextToken(String) in the 'modern' approaches... if anyone so happens to really require it. – h.j.k. 5 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.