JDK-7032377 : MatchResult and Pattern should provide a way to query names of named-capturing groups
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util.regex
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • Submitted: 2011-03-30
  • Updated: 2023-08-24
  • Resolved: 2023-08-24
Related Reports
Duplicate :  
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
http://download.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

The new RegExp packages supports named capturing groups through Match.group(String name), which is fine. But it lacks the method to get the name of the group from within the Match(Result).

In my case I'd like to loop through all matches and from within that match, check if there's a named capturing group associated. If so, I'd like to get the name and put the match into an Map<String groupname, String result>.

Would be great to have this enchancements in JDK7.

JUSTIFICATION :
It makes the named capturing groups usefull in a lot more cases.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
MatchResult.getGroupName(); oid.
ACTUAL -
No function available.

CUSTOMER SUBMITTED WORKAROUND :
Having some manual Mapping between the group index and the name to associate.

Comments
Pattern could expose a groupNames() method returning an unmodifiable Set<String>. MatchResult could expose end(String), group(String) and start(String), with the same semantics these methods have in Matcher. There are two implementors of MatchResult in the JDK, namely Matcher itself and Matcher's nested static ImmutableMatchResult, whose instances are returned by Matcher::toMatchResult. Adding the methods to the interface shouldn't be too incompatible for other implementations outside the JDK, if any.
10-08-2022

I'm augmenting this bug to cover querying of named-capturing groups in both MatchResult and Pattern. They're logically distinct, but closely enough related that I find it hard to imagine doing one without the other. (In fact one approach might be to allow MatchResult to keep a reference to the Pattern it matched, so solving this for Pattern would also solve it for MatchResult.) See JDK-8249601 for information about uses for getting named groups from Pattern.
01-09-2020

More information from the submitter of JDK-8249601: In my code I never used MatchResult (mentioned in JDK-7032377). My use-cases are: "instance of Pattern" -> matcher(String).matches() -> "instance of Matcher" -> check if groupName exists, get value via group(name) --> therefore extending of MatchResult will not help in my use-cases. Matcher has back-reverence on originating pattern and it is accessible via 'public Pattern pattern()' - therefore in these use-cases it is enough to add "introspection of named groups" only into Pattern class. Regarding particular implementation: * in 99% of cases I just need to check if groupName exists in pattern - this is recommended to be implemented via performance-friendly method 'Pattern.hasGroup()' * in 1% of cases I would need real "introspection of named groups" - for that case additional temporary read-only HashMap wrapper will be created via 'public Map<String, Integer> namedGroups()'. If needed, user will be able to easily build reverse map [index -> name] from that data.
07-08-2020

I had closed JDK-8249601 as a duplicate of this bug. It's sort-of asking for the same thing, but it's requesting access to named groups of a Pattern, not a MatchResult. It's unclear whether both are necessary. It might be reasonable to ask a compiled Pattern what groups it has, before it's matched anything. But I suspect the point of wanting to do so is to query a Matcher (and by extension, eventually, a MatchResult) for values matched by named-capturing groups. More analysis needed.
16-07-2020

What's being asked for is a way to map group numbers to group names. It's not quite clear to me why this mapping would be useful. Perhaps it's just a way that the submitter thought would be easy to enumerate the group names. An API to retrieve the group names would be more helpful, I think. A text processor could pass around MatchResults obtained from matching using several different patterns with named matching groups. These MatchResults are essentially "beans" of pieces of matches. Some downstream process could inspect which matches are available from each result and extract the pieces appropriately. If the query method were to return a Set<String>, this could simply be the keyset (possibly wrapped or copied to be unmodifiable) of the internal map of group names. An alternative would be to return a List<String> which is the list of group names in the order in which they appear in the original pattern. I'm not sure this is useful. The point of using names is to insulate the consumer from things like order dependencies, which numbered groups suffer from. Re-introducing ordering would tend to allow such order dependencies to creep back in. Another alternative would be to return a List<String> whose indexes correspond to the group numbers. This has the same problems as noted above, and additionally groups that have no names would have to have placeholders in this list: probably null. Also, group 0 has no name, so that would always be null as well. Again, doesn't seem useful. Still another alternative would be to expose a Map<String, String> which is a map from the group name to the text that it matches. The text is probably the most useful bit extracted from the MatchResult. One problem is that for groups that haven't matched, would the value be null? Or would the entry be absent? (A non-matching group is represented in a MatchResult with a start() and end() returning -1, and group() returning null.) Such a map is fairly simply to construct from the set of group names: MatchResult mr = matcher.toMatchResult(); Map<String, String> results = mr.groupNames() .stream() .filter(name -> mr.start(name) >= 0) .collect(Collectors.toMap(name -> name, name -> mr.group(name))); Note that this filters out groups that haven't matched. The set of group names seems to be the simplest and the most straightforward API.
04-10-2019

There is a possibility of using Java 8 default methods for this. This request has also come up in other forums, e.g., http://stackoverflow.com/questions/15588903/get-group-names-in-java-regex
12-02-2015

EVALUATION Reasonable request, the only problem is that the MatchResult is an interface, which brings in the compatiblity risk into the equation (any change to a public interface will break any existing class that implements this interface), the only "way" is to have a MatchResult2.
30-03-2011