Java: template behaves differently in scanner

Affects strange regex matching behavior in Java. The first output command prints true

as expected, but when the same line is packed into Scanner

, the output is false

. What am I doing wrong?

public static void main(String[] args) {
  Pattern p = Pattern.compile(" *\\[");
  System.out.println(p.asPredicate().test("[]")); //true

  Scanner s = new Scanner("[]");
  System.out.println(s.hasNext(" *\\[")); //false
}

      

+3


source to share


2 answers


From public boolean hasNext(String pattern)

documentation :

Returns true if the next token matches the pattern built from the specified string.

Here the next token is []

not easy [

(since the delimiter is one or more spaces), but the pattern " *\\["

does not exactly match that token ( ]

does not match), so you are informed about it by the result false

.

If you want to check if a token starts with [

, you can add .*

at the end of your template to match the remainder of the token. You can also remove *

, since the space is the default delimiter, so it cannot be part of the token.




When

Pattern p = Pattern.compile(" *\\[");
System.out.println(p.asPredicate().test("a[]")); //true

      

If you look at the code asPredicate

, you can see that it is implemented as:

public Predicate<String> asPredicate() {
    return s -> matcher(s).find();
}

      

find()

the method does not check if the whole string matches the pattern, but tries to find even the part of it that matches the pattern. Since it []

contains zero or more spaces followed by [

you, you see the result true

.

+6


source


According to the Predicate.test

description from the Javadoc:

... true if the input argument matches the predicate, otherwise false

Something that is not explicitly written in the Javadoc, but implies that the method test(T t)

does not match the method String.matches(String)

where the starting and ending anchors are implicit. test

method, on the other hand, does not match the full string and you will need to use anchors in your regex to make it behave like methods String.matches

or Scanner.hasNext(Pattern )

.



The following code will give a consistent result false

from both calls

final String input = "[]";
final String re = "^ *\\[$"; // note use of anchors in the regex
final Pattern p = Pattern.compile(re);

System.out.println(p.asPredicate().test(input)); // false

Scanner s = new Scanner(input);
System.out.println(s.hasNext(p)); //false
s.close();      

      

0


source







All Articles