1

我目前正在研究一个 Scala 项目,并将其转换为 Java。一切都很好,但我偶然发现了这个片段:

    Pattern fileNamePattern = Pattern.compile("^(\\w+).*(_\\w+\\.xml)$");


    new File(filePath).getName match {
        case FileNamePattern(first, last) => return first + last
        case n => return n
    }

我理解正则表达式,一个或多个字母、数字或标点符号,后跟 0 个或多个字符,然后是一个或多个字母、数字或标点符号。此函数的目的是从文件路径中获取文件名,但这在 Java 中确实非常简单,所以我认为 Scala 开发人员不会让它变得如此不必要的复杂。

问题是,我不想继续前进并假设开发人员是个白痴,也许他们正在尝试做一些更聪明的事情,而我对 Scala 的缺乏经验阻止了我看到它。所以有人可以解释一下:

  • 带有匹配的语法
  • 第一个和最后一个到底是从哪里来的
  • 导致此代码段的 Java 等价物的等价物 / 文档
def getFileName(filePath: String): String = {

    if(filePath == null || filePath.trim.length == 0) {
      return filePath
    }

    val FileNamePattern = new Regex("^(\\w+).*(_\\w+\\.xml)$")

    new File(filePath).getName match {
         case FileNamePattern(first, last) => return first + last
         case n => return n
    }
}
4

1 回答 1

3

match构造用于进行模式匹配。基本上,左侧match是与右侧存在的模式匹配的对象。生成的代码按它们出现的顺序测试每个模式,如果一个模式与对象匹配,=>则执行后面的代码。

表达式中的firstlast变量match是由模式匹配机制绑定的变量,当它们出现的模式与对象匹配时。它们的值将是匹配对象图中的对应值。换句话说,它们是由模式隐式声明的,并且会在之后的“consequence”子句中正确初始化=>

经典例子:

trait Expr

case class Const(val value: Int) extends Expr
case class Add(val left: Expr, val right: Expr) extends Expr

def evaluate(exp: Expr): Int = exp match {
    case Const(cv) => cv
    case Add(exp1, exp2) => evaluate(exp1) + evaluate(exp2)
    case _ => throw new IllegalArgumentException("did not understand: " + exp)
}

Scala 的正则表达式对象为模式匹配提供了特殊的支持(通过它们的unapply/unapplySeq方法)。在这种情况下,如果正则表达式与返回的字符串匹配getName,则变量firstlast将分别绑定到匹配正则表达式的第一个子组和第二个子组的子字符串。

Java 没有match类似的语言结构。等效的 Java 代码会非常冗长和麻烦。它可能看起来像

final String name = (new File(filePath).getName());
final Matcher matcher = FileNamePattern.match(name);

if (matcher.matches()) {

    final String first = matcher.group(1);
    final String last = matcher.group(2);
    return first + last;

} else {

    return name;
}
于 2013-08-07T11:10:32.270 回答