tags:

views:

142

answers:

7

I am wondering why the results of the java regex pattern.matcher() and pattern.matches() differ when provided the same regular expression and same string

String str = "hello+";
Pattern pattern = Pattern.compile("\\+");
Matcher matcher = pattern.matcher(str);

while (matcher.find()) {
    System.out.println("I found the text " + matcher.group() + " starting at " 
        + "index " + matcher.start() + " and ending at index " + matcher.end());
}

System.out.println(java.util.regex.Pattern.matches("\\+", str));

The result of the above are:

I found the text + starting at index 5 and ending at index 6
false

I found that using an expression to match the full string works fine in case of matches(".*\\+").

+6  A: 

pattern.matcher(String s) returns a Matcher that can find patterns in the String s. pattern.matches(String str) tests, if the entire String (str) matches the pattern.

In brief (just to remember the difference):

  • pattern.matcher - test if the string contains-a pattern
  • pattern.matches - test if the string is-a pattern
Andreas_D
actually, `find()` is the difference. the Matcher itself is not - `matcher.matches()` still returns false
Bozho
@Bozho, yes, I know. But because the OP is comparing a method that returns a `Matcher` instance with another method that returns a boolean and wonders why their results are not comparable, I decided to write an easy answer, knowing that I couldn't score with it on SCJP exams ;-)
Andreas_D
You're also glossing over the fact that `Pattern.matches` is a static method. Try to call `pattern.matches()` with no arguments (`pattern` being an instance of `Pattern`) and your code won't even compile.
Alan Moore
A: 

If you add this println():

Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());

It still prints false. The .matches() method (both Pattern.matches() and Matcher.matches()) will attempt to match the entire string; it's as if the regex had the ^ and $ anchors, while find() scans it for partial matches.

NullUserException
A: 

Matcher.find() attempts to find the next subsequence of the input sequence that matches the pattern.

Pattern.matches(String regex, CharSequence input) compiles the regex into a Matcher and returns Matcher.matches().

Matcher.matches attempts to match the entire region (string) against the pattern (Regex).

So, in your case, the Pattern.matches("\\+", str) returns a false since str.equals("+") is false.

The Elite Gentleman
+2  A: 

Pattern.matches is testing the whole String, in your case you should use:

 System.out.println(java.util.regex.Pattern.matches(".*\\+", str));

Meaning any string and a + symbol

greuze
What if the target string were `hello+world`?
Alan Moore
It depends on the needs. In that case, it would be:System.out.println(java.util.regex.Pattern.matches(".*\\+.*", str));
greuze
+2  A: 

From the Javadoc, see the if, and only if, the entire region section

   /**
     * Attempts to match the entire region against the pattern.
     *
     * <p> If the match succeeds then more information can be obtained via the
     * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods.  </p>
     *
     * @return  <tt>true</tt> if, and only if, <b>the entire region</b> sequence
     *          matches this matcher's pattern
     */
    public boolean matches() {
        return match(from, ENDANCHOR);
    }

So if your String was just "+", you'd get a true result.

karianna
You're right, but ... uhm ... I see no bold text.
DerMike
Well that's just embarrassing, let me try to fix that.
karianna
A: 

Well thanks all, I got it. Thanks for explaining the working of matcher.find() and matcher.matches(), now these english words find and matches makes more sense to me :).

samarjit samanta
You do not reply to your post by adding another post to the answer block. What you do is you pick an answer that best represents the solution to your problem and click the tick mark found under the score. To post a comment, put it in a comment block. Start voting the answers to have an acceptable acceptance rate.
The Elite Gentleman
Correct, thanks anyways, I was not logged in while posting the question so I didn't have those options to reply, So now I registered and hence am able to post comment, now next time i ask a question after logging in probably i can get a chance to vote too.
samarjit samanta
A: 

I think your question should really be "When should I use the Pattern.matches() method?", and the answer is "Never." Were you expecting it to return an array of the matched substrings, like .NET's Matches methods do? That's a perfectly reasonable expectation, but no, Java has nothing like that.

If you just want to do a quick-and-dirty match, adorn the regex with .* at either end, and use the string's own matches() method:

System.out.println(str.matches(".*\\+.*"));

If you want to extract multiple matches, or access information about a match afterward, create a Matcher instance and use its methods, like you did in your question. Pattern.matches() is nothing but a wasted opportunity.

Alan Moore