我想写一个函数,它可以根据regex匹配字符串,并使用所有组匹配作为参数执行回调。
我想出了这个,它很有效:
private static void parse(String source, String regex,
Consumer<String[]> callback) {
//convert regex groups 1..n into integer array 0..n-1 and call
//consumer callback with this array
Matcher m = Pattern.compile(regex).matcher(source);
String[] ret = new String[m.groupCount()];
if (m.matches()) {
for (int i=0; i<m.groupCount(); i++) {
ret[i] = m.group(1+i);
}
callback.accept(ret);
}
}
然后你可以进行
parse("Add 42,43", "Add (\d+?),(\d+?)", p -> processData(p[0],p[1]));
理想情况下,我想做的是这个
parse("Add 42,43", "Add (\d+?),(\d+?)", (x,y) -> processData(x,y));
最优雅的方式是什么?我唯一能想到的就是用1..n参数声明多个函数接口,并使用重写来处理它。有更好的想法吗,也许是反射?
据我所知,问题是数组中的元组初始化是否有语法糖,即:
val (hour, minutes, seconds) = new String[]{"12", "05", "44"};
除了它隐藏在lambda参数声明中。
据我所知,Java8中没有这样的语法,您的方法似乎是最方便的。然而,在Scala中有一个问题:有没有一种方法可以从Scala中的数组或列表初始化多个变量?。
Scala中也有类似的指令:
scala> val s = "Add 42,43"
scala> val r = "Add (\d+?),(\d+?)".r
scala> val r(x,y) = s
x: String = 42
y: String = 43
由于我现在自己解决了这个问题,我将在这里发布我提出的解决方案。如果有人提出了一个更好的方法,也许是方法链接或更通用的方法,我会很乐意给出答案。
你可以这样使用下面的类:
Sring msg = "add:42,34";
ParseUtils.parse(msg, "add:(\d+),(\d+)", (int x,int y) -> simulator.add(x, y));
ParseUtils.parse(msg, "add:(\d+),(\d+)", simulator::add); //IntBiConsumer match
ParseUtils.parse(msg, "add:(.*?),", System.out::println);
这是类(我省略了琐碎的错误处理和布尔值返回,如果不匹配):
public class ParseUtils {
@FunctionalInterface
public interface Consumer { void accept(String s); }
@FunctionalInterface
public interface BiConsumer { void accept(String a, String b); }
//... you can add TriConsumer etc. if you need to ...
@FunctionalInterface //conveniently parses integers
public interface IntBiConsumer { void accept(int x, int y); }
// implementations -----
public static void parse(String src, String regex, Consumer callback) {
callback.accept(parse(src, regex)[0]);
}
public static void parse(String src, String regex, BiConsumer callback) {
String[] p = parse(src, regex);
callback.accept(p[0],p[1]);
}
public static void parse(String src, String regex,
IntBiConsumer callback) {
String[] p = parse(src, regex);
callback.accept(Integer.parseInt(p[0]), Integer.parseInt(p[1]));
}
public static String[] parse(String source, String pattern) {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(source);
String[] ret = new String[m.groupCount()];
if (m.matches()) {
for (int i=0; i<m.groupCount(); i++) {
ret[i] = m.group(1 + i);
}
}
return ret;
}
}