Determine whether a word appears in a sentence Given an array of words representing a sentence and a word to search for, the method must determine whether the word appears in the sentence.

Specifications


Case insensitive.
The arguments are never null.
The sentence is in the English language.




/**
 * A case-insensitive search on a sentence to find whether a given word can be found in it. It
 * keeps certain punctuation in mind.
 *
 * @param  aSentence An array of words forming a sentence. Cannot be {@code null}.
 * @param  aWord     The word to search for. Cannot be {@code null}.
 *
 * @return {@code true} if the word appeared at least once in the sentence, {@code false}
 *         otherwise.
 */
public boolean sentenceContainsWord(final String[] aSentence, String aWord)
{
  // The search is case-insensitive
  aWord = aWord.toLowerCase();

  // Loop through the words in the sentence
  for (int i = 0; i &lt; aSentence.length; i++)
  {
    String sentenceWord = aSentence[i];

    // If the word in the sentence matches, return immediately
    if (sentenceWord.toLowerCase().equals(aWord))
    {
      return true;
    }

    // The word could end with punctuation like a comma or a dot
    int lastSentenceWordIndex = sentenceWord.length() - 1;
    String lastCharacter = Character.toString(sentenceWord.charAt(lastSentenceWordIndex));
    if (lastCharacter.matches("[.,:;]") &amp;&amp; sentenceWord.substring(0, lastSentenceWordIndex).equals(aWord))
    {
      return true;
    }
  }

  return false;
}
The String class provides the method .equalsIgnoreCase(). It seems to me, calling .toLowerCase() and then .equals() has to process the string twice, but could be done in a single run.

It is unclear how well the sentence is processed before it enters the method as array. I will be a little optimistic in my assumptions.

You can give it a cleaner structure using streams [if you are using Java 1.8 at least]. It provides a method .noneMatch(predicate) which is short-circuiting just as your loop is now. Using streams makes it easy to add a cascade of string preprocessing steps before the final comparison. Removing punctuation as you have it now, it could be written as follows:

import java.util.Arrays;

public static boolean sentenceContainsWord(final String[] aSentence, final String aWord)
{
    return !Arrays.stream(aSentence)
                  .map((w) -&gt; w.replaceAll("\\.|,|:|;", ""))
                  .noneMatch((w) -&gt; w.equalsIgnoreCase(aWord));
}


My optimistic assumption here is that there is no punctuation in between a word which might result from a too simplistic tokenisation (e.g. .split(" ")). Using .replaceAll() removes a lot of the clutter around finding trailing punctuation and extracting substrings.

Resources:  


Java Doc:
Stream::noneMatch
Java Doc:
String::equalsIgnoreCase
Java Doc:
String::replaceAll