First of all your two methods are both wrong. You're counting the number of space-separated "things" (needn't be words) in the first method rather than counting the number of non-space sequences:
jshell> ("some words").split(" ") $2 ==> String[3] { "some", "", "words" } jshell> (" leading and trailing spacing ").split(" ") $3 ==> String[5] { "", "leading", "and", "trailing", "spacing" } jshell> ("").split(" ") $4 ==> String[1] { "" } jshell> (" ").split(" ") $5 ==> String[0] { }
as you can see the word count does not match the space-delimited content count. Counting the spaces suffers from the same issues, except it will also fail on strings with "only" trailing spacing.
Both the RegEx and the for-loop run in linear time O(n), having to visit each character exactly once; using a RegEx requires first compiling the RegEx, but for such a simple RegEx we can reasonably neglect this. This does not mean that they take the same time to complete though, the constant factor may very well differ. As others have pointed out already the RegEx + splitting obviously incurs a significant overhead - especially as this requires auxiliary space O(n) whereas the simple for loop counting variant requires just constant auxiliary space O(1) to keep track of the count and the current index.
Fixing & improving your code using RegEx is quite easy:
int count = 0; Matcher matcher = Pattern.compile("\\S+").matcher(message); while (matcher.find()) count++;
You'll likely want to use a character class like \w (alphanumerics) for words rather than looking for non-space characters \S.
Or if you want to implement this manually using the for-loop as it may be slightly faster:
int count = message.charAt(0) == ' ' ? 0 : 1; // does the text start with a non-space character? for (int i = 1; i < message.length; i++) { // beginning of word: transition space -> non-space if (message.charAt(i) != ' ' && message.charAt(i-1) == ' ') count++ }
foo baras 4 words.