使用正则表达式解析字符串时的Java 8 lambda表达式回调类型



我想写一个函数,它可以根据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;
    }
}

最新更新