As you know (see Appendix B),
a capturing group is a part of a pattern, that is marked by parentheses (without '?' following the opening one).
Such group captures a corresponding part of input, so one can obtain its contents using one of
MatchResult's methods by supplying a group number.
Such numbering is usually done automatically, according to an order of precedence of opening round brackets as they
appear in a pattern.
A problem arises when somebody's application hardly relies on a lot of patterns.
Patterns tend to change over the time. Some changes may affect a group order which leads
to inconsistency both in pattern backrefences and hardcoded group numbers.
Such inconsistencies are very hard to find, resulting in code unmaintainability.
Named groups address this problem by allowing to assign either a symbolic name
or an explicit numeric id to a particular group.
To assign a symbolic name to a group, a name (a word conforming to a Java identifier syntax) should
be enclosed in curly brackets just after the opening parenthesis:
Pattern hms=new Pattern("({Hour}\\d\\d):({Minute}\\d\\d):({Second}\\d\\d)");
//A group name is one in a curly brackets just after the opening parenthesis
Matcher m=hms.matcher(someStr);
if(m.matches()){
System.out.println("Hour: "+m.group("Hour"));
System.out.println("Minute: "+m.group("Minute"));
System.out.println("Second: "+m.group("Second"));
}
It's not so hard to guess that under the hood of a symbolic name there should
be a numeric id. Yes, it really is, and one can take it from a Pattern by method
groupId(String)
and use it the same way as if it were an ordinal group id:
//hms and m are defined above
int hourId=hms.groupId("Hour").intValue();
System.out.println(hourId); //prints "1"
System.out.println(m.group(hourId)); //prints an hour
If a word in curly brackets is a decimal number, the group is forced to have
a corresponding numeric id, without assigning any symbolic name:
Pattern ordinal=new Pattern("(\\w+)-(\\w+)-(\\w+)");
Pattern forced=new Pattern("({3}\\w+)-({2}\\w+)-({1}\\w+)");
//forced id is a number in curly brackets just after the opening parenthesis.
//Except the group numbering, the two patterns above are equivalent
String str="one-two-three";
Matcher om=ordinal.matcher(str);
Matcher fm=forced.matcher(str);
om.find();//surely finds
fm.find();//surely finds
System.out.println(om.group(1)+","+om.group(2)+","+om.group(3));
//prints "one,two,three"
System.out.println(fm.group(1)+","+fm.group(2)+","+fm.group(3));
//prints "three,two,one"
System.out.println(forced.groupId("1"));
//prints "null" because such symbolic name wasn't assigned
System.out.println(fm.group("1"));
//throws IllegalArgumentException stating that such symbolic name wasn't assigned
Try this right now in a demo applet using the following pattern and target: