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

使用正则表达式解析字符串时的Java 8 lambda表达式回调类型,java,lambda,java-8,Java,Lambda,Java 8,我想写一个函数,它可以根据正则表达式匹配字符串,并以所有组匹配项作为参数执行回调 我想到了这个,它是有效的: private static void parse(String source, String regex, Consumer<String[]> callback) { //convert regex groups 1..n into integer array 0..n-1

我想写一个函数,它可以根据正则表达式匹配字符串,并以所有组匹配项作为参数执行回调

我想到了这个,它是有效的:

 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);
        }
    }
私有静态void解析(字符串源、字符串正则表达式、,
消费者回调){
//将正则表达式组1..n转换为整数数组0..n-1并调用
//使用此数组的使用者回调
Matcher m=Pattern.compile(regex.Matcher)(源代码);
String[]ret=新字符串[m.groupCount()];
如果(m.matches()){
对于(int i=0;i处理数据(p[0],p[1]);

理想情况下,我希望能够做到这一点

parse(“add42,43”,“Add(\\d+?),(\\d+?)”,(x,y)->processData(x,y));


最优雅的方法是什么?我能想到的唯一方法是用1..n参数声明多个函数接口,并使用重写来处理它。有没有更好的主意,也许是反射?

据我所知,问题是是否有一种语法糖用于数组的元组初始化,即:

 val (hour, minutes, seconds) = new String[]{"12", "05", "44"};
…但它隐藏在lambda arguments声明中

据我所知,Java8中没有这样的语法,您的方法似乎是最方便的

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);
下面是这个类(我省略了简单的错误处理和布尔返回,如果不匹配):

公共类ParseUtils{
@功能接口
公共接口使用者{void accept(字符串s);}
@功能接口
公共接口双消费者{void accept(字符串a,字符串b);}
//…您可以添加三角豆等。如果需要。。。
@FunctionInterface//方便地解析整数
公共接口IntBiConsumer{void accept(intx,inty);}
//实现-----
公共静态void解析(字符串src、字符串regex、使用者回调){
accept(parse(src,regex)[0]);
}
公共静态void解析(stringsrc、stringregex、BiConsumer回调){
String[]p=parse(src,regex);
callback.accept(p[0],p[1]);
}
公共静态void解析(字符串src、字符串regex、,
IntBiConsumer回调){
String[]p=parse(src,regex);
accept(Integer.parseInt(p[0]),Integer.parseInt(p[1]);
}
公共静态字符串[]解析(字符串源、字符串模式){
Pattern p=Pattern.compile(Pattern);
匹配器m=p.Matcher(源);
String[]ret=新字符串[m.groupCount()];
如果(m.matches()){

对于(int i=0;iI不完全确定您想要的是什么,但似乎varargs和lambda不能以您想要的方式混合使用。为了使用lambda,目标类型必须是函数接口,其单个方法有固定数量的参数,在编译时确定。问题的根源是直到运行时才知道有多少参数组在regexp中。如果只有一个组,如何调用
processData
,因为它似乎需要两个参数?事实上,我认为,调用方知道regexp中有多少组,方法重写的想法可能会起作用。只是不使用单个方法。感谢Scala中的解决方案。我不知道这个技巧。我不会我想看看Java 8中是否还有其他解决方案。不是元组初始化,而是可能使用1、2或3个参数进行重写,然后使用数组进行更多操作。这将涵盖许多简单的解析情况。我想做重写是一种方法,我正要编写一些骨架代码,但有点懒。(我还想知道java的新型推理系统有多灵活)。
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;
    }

}