Rationale for Matcher throwing IllegalStateException when no 'matching' method is called
Actually, you misunderstood the documentation. Take a 2nd look at the statement you quoted: -
attempting to query any part of it before a successful match will cause an
IllegalStateException to be thrown.
A matcher may throw IllegalStateException
on accessing matcher.group()
if no match was found.
So, you need to use following test, to actually initiate the matching process: -
- matcher.matches() //Or
- matcher.find()
The below code: -
Matcher matcher = pattern.matcher();
Just creates a matcher
instance. This will not actually match a string. Even if there was a successful match.
So, you need to check the following condition, to check for successful matches: -
if (matcher.matches()) {
// Then use `matcher.group()`
}
And if the condition in the if
returns false
, that means nothing was matched. So, if you use matcher.group()
without checking this condition, you will get IllegalStateException
if the match was not found.
Suppose, if Matcher
was designed the way you are saying, then you would have to do a null
check to check whether a match was found or not, to call matcher.group()
, like this: -
The way you think should have been done:-
// Suppose this returned the matched string
Matcher matcher = pattern.matcher(s);
// Need to check whether there was actually a match
if (matcher != null) { // Prints only the first match
System.out.println(matcher.group());
}
But, what if, you want to print any further matches, since a pattern can be matched multiple times in a String, for that, there should be a way to tell the matcher to find the next match. But the null
check would not be able to do that. For that you would have to move your matcher forward to match the next String. So, there are various methods defined in Matcher
class to serve the purpose. The matcher.find()
method matches the String till all the matches is found.
There are other methods also, that match
the string in a different way, that depends on you how you want to match. So its ultimately on Matcher
class to do the matching
against the string. Pattern
class just creates a pattern
to match against. If the Pattern.matcher()
were to match
the pattern, then there has to be some way to define various ways to match
, as matching
can be in different ways. So, there comes the need of Matcher
class.
So, the way it actually is: -
Matcher matcher = pattern.matcher(s);
// Finds all the matches until found by moving the `matcher` forward
while(matcher.find()) {
System.out.println(matcher.group());
}
So, if there are 4 matches found in the string, your first way, would print only the first one, while the 2nd way will print all the matches, by moving the matcher
forward to match the next pattern.
I Hope that makes it clear.
The documentation of Matcher
class describes the use of the three methods it provides, which says: -
A matcher is created from a pattern by invoking the pattern's matcher
method. Once created, a matcher can be used to perform three different
kinds of match operations:
The matches method attempts to match the entire input sequence
against the pattern.The lookingAt method attempts to match the input sequence, starting
at the beginning, against the pattern.The find method scans the input sequence looking for the next
subsequence that matches the pattern.
Unfortunately, I have not been able find any other official sources, saying explicitly Why and How of this issue.
IllegalStateException: No match found when getting match group
Problem is this line:
streetAddress = streetAddressMatch.group();
You are calling group()
without calling streetAddress.find()
or streetAddress.matches()
before.
Java Pattern & Matcher - Not able to extract pattern if starting character is a \
After making your matcher, you need to call find()
(so it will actually try and make a match) before calling group()
to get the group from the match it found.
From the docs for find()
:
If the match succeeds then more information can be obtained via the start, end, and group methods.
RegEx Pattern not matching in JAVA
You need to call Matcher#find()
to actually get a match:
Pattern p = Pattern.compile("([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)");
Matcher matcher = p.matcher("1-1-3-1-4");
if (matcher.find()) {
System.out.println(matcher.group(0))
}
If you were expecting multiple matches, you could use a while
loop instead of an if
statement.
Also note that you actually have five capture groups in your patterns. Capture groups are denoted by placing a portion of the pattern in parentheses. If you don't intend/need to capture the five separated numbers in your pattern individually, then you can consider telling the regex engine not to capture them, e.g. use this:
Pattern p = Pattern.compile("(?:[0-9]+)-(?:[0-9]+)-(?:[0-9]+)-(?:[0-9]+)-(?:[0-9]+)");
Demo
Why does a Mattcher throw an exception after a successful find
As per the last update on my question, restarting IntelliJ and recompiling my code fixed things.
Java is not able to find a match for regex
find() must be called on the Matcher before group() can be called. Your code will work if you change it to:
String path1 = "TEST(\":\")/Role[@name=\"TestRole\"]";
String pattern = "TEST\\(\":\"\\)/(\\w+)\\[@name=\"(.*)\"]";
Pattern pat = Pattern.compile(pattern);
Matcher match = pat.matcher(path1);
if ( match.find() ) {
System.out.println(match.group());
}
If condition can be used for a single match, and while loop can be used for multiple matches.
Java - Matcher throws IllegalStateException after accessing group
You need to use:
if (m.find() && m.groupCount() == 1) {
sourceTypes.add(m.group(1)); //line 28
}
i.e. call find
or matches
before group()
method.
Matcher find a pattern but throw No match available on `start` method
Problem is that you're using pattern.matcher(text)
again and that creates another Matcher
instance and when you call start()
on a new instance it throws exception since find
or matches
or lookingAt
has not been called before.
You may use it like this:
String text = "Hello bob, remind me to do a lot of things today";
final Pattern pattern = Pattern.compile("remind.*\\hto\\h");
Matcher m = pattern.matcher(text); // create it only once
// Looking for "remind <anyWord> to "
if (m.find()) {
System.err.println( "Start: " + m.start() + ", match: " + m.group() );
}
Also note changes in your regex. \h
matches a horizontal whitespace whereas .to.
will match any character before and after to
hence your regex will match:
"remind me to do a lot of things tod"
instead of intended:
"remind me to do "
Related Topics
Java:Cannot Format Given Object as a Date
Is There a Good Natural Language Processing Library
Java Date Parsing with Microsecond or Nanosecond Accuracy
How to Use Java.String.Format in Scala
How to Check If Two Words Are Anagrams
How to Add a Resources Folder to My Java Project in Eclipse
Parsing a Date's Ordinal Indicator ( St, Nd, Rd, Th ) in a Date-Time String
How to Replace Case-Insensitive Literal Substrings in Java
Io Error: the Network Adapter Could Not Establish the Connection
How to Go About Formatting 1200 to 1.2K in Java
Using Generics in Spring Data JPA Repositories
How to Get the Size of an Array, a Collection, or a String in Java
Comparing Two Java.Util.Dates to See If They Are in the Same Day