Pattern.compile("\\(([^)]+)\\)");
The Pattern is always the same so you may just as well make it a private static final
constant. This will avoid having to recompile the pattern each time.
Arrays.asList(/*..*/).stream().collect(Collectors.toList());
Why this dance? Arrays.asList returns a List. You only do a stream on the return result.
final List<String> list = Arrays.asList(matcher.group(1).split(","));
list.stream().forEach(a ->
{
final String[] ar = a.split("->");
map.put(ar[0], ar[1]);
});
However a Pattern an return a Stream split according to the pattern directly:
Pattern COMMA_PATTERN = Pattern.compile("\\s*,\\s*");
COMMA_PATTERN.splitAsStream(matcher.group(3)).forEach(a ->
{
//...
}
You can use a single match of a Pattern to find both the leading values and the string inside the parenthesis:
private static final Pattern FULL_PATTERN = Pattern.compile("^(\\$\\w+)\\s*=>\\s*(\\w+)\\s*\\(([^)]+)\\)$");
private static final Pattern KEY_VALUE_PATTERN = Pattern.compile("(\\w+)\\s*->\\s*(\\w+)");
private static final Pattern COMMA_PATTERN = Pattern.compile("\\s*,\\s*");
public static Macro getMacro(String str) {
final Macro macro = new Macro();
final Map<String, String> map = new HashMap<String, String>();
final Matcher matcher = FULL_PATTERN.matcher(str);
if(!matcher.matches()) {
throw new IllegalArgumentException("...");
}
COMMA_PATTERN.splitAsStream(matcher.group(3)).forEach(a ->
{
final Matcher kvMatcher = KEY_VALUE_PATTERN.matcher(a);
if(!kvMatcher.matches()){
throw new IllegalArgumentException("...");
}
map.put(kvMatcher.group(1), kvMatcher.group(2));
});
macro.setMap(map);
macro.setKey(matcher.group(1));
macro.setType(matcher.group(2));
return macro;
}
You'll note I added \\s*
to various points in each pattern, This lets you ignore the whitespace that may surround the operators.
The \\w
in a Pattern means a word character. If you only want alphanumeric +undescore then you'llneed to replace each instance of it with [\\p{Alnum}_]