Java: Example - Replace word

Problem: Write a method to replaces all occurences a word in a string with another word. Assume the method signature is
   static String replaceWord(String original, String find, String replacement)
Note that Strings are immutable, so we must create a new String. The word "replace" is probably misleading. Also, the method is static because it doesn't reference any instance variables. This allows some optimizations by the compiler.

A simple, but incorrect, solution

This first attempt only replaces one word, but we could fix that up later with a loop -- but it's not worth the effort because it's wrong anyway.
//--------------------------------------------- replaceWord() 
// BAD BAD BAD BAD BAD  
static String replaceWord(String original, String find, String replacement) {
    int i = original.indexOf(find);
    if (i < 0) {
        return original;  // return original if 'find' is not in it.
    }
  
    String partBefore = original.substring(0, i);
    String partAfter  = original.substring(i + find.length());
  
    return partBefore + replacement + partAfter;
}
This example method replaces the first occurrence of a one string with another. If we execute the following code,
   t = "A great man";
   s = replaceWord(t, "man", "woman"); 
the value in s will be "A great woman". Ok, but what if we changed the orginal string to contain the word "human", or anything else that contained a substring, but not a separate word, that has "man" in it.
   t = "A great human";
   s = replaceWord(t, "man", "woman");
Now s will contain "A great huwoman". Not what was intended.

The solution is to know about "words"

Simply finding a substring isn't sufficient. There are several ways to solve the problem.

StringTokenizer solution

This replaces all occurences of a "word", not just the first.
static String replaceWord(String original, String find, String replacement) {
    String result = "";
    String delimiters = "+-*/(),. "
    StringTokenizer st = new StringTokenizer(original, delimiters, true);
    while (st.hasMoreTokens()) {
        String w = st.nextToken();
        if (w.equals(find)) {
           result = result + find;
        } else {
           result = result + w;
        }
    }
    return result;
}
This will break the string into tokens, consisting of the text between delimiters, as well as the tokens consisting of the delimiters. The true parameter causes the delimiters to also be returned as tokens. You might not need them if you are only interested in what comes between them. Naturally, you would choose the delimiters appropriate to your problem.

Buiding a string by sucessive concatenations is inefficient and should be replaced by StringBuffer for efficiency, but this above is just a first draft.