重载方法调用有替代方法:String.format

use*_*558 6 string unicode stringbuilder scala

我在下面编写了下面的Scala代码来处理我传入的String,格式化String,将其附加到a StringBuilder并将String带有转义的unicode 的格式化返回给我的调用者以进行其他处理.

Scala编译器在存在String.format以下错误的调用行时抱怨以下内容:

带备选方法的重载方法值格式:(x$1; java.util.Locale; x$2: String, X$3: Object*) (x$1:String,x$2: Object*)无法应用字符串(*String, Int)

class TestClass {    
    private def escapeUnicodeStuff(input: String): String = {
            //type StringBuilder = scala.collection.mutable.StringBuilder
            val sb = new StringBuilder()
            val cPtArray = toCodePointArray(input) //this method call returns an Array[Int]
            val len = cPtArray.length
            for (i <- 0 until len) {
              if (cPtArray(i) > 65535) {
                val hi = (cPtArray(i) - 0x10000) / 0x400 + 0xD800
                val lo = (cPtArray(i) - 0x10000) % 0x400 + 0xDC00
                sb.append(String.format("\\u%04x\\u%04x", hi, lo)) //**complains here**
              } else if (codePointArray(i) > 127) {
                sb.append(String.format("\\u%04x", codePointArray(i))) //**complains here**
              } else {
                sb.append(String.format("%c", codePointArray(i))) //**complains here**
              }
            }
            sb.toString
          }

    }
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?如何清理代码以实现格式化String的目的?在此感谢Scala专家

Ben*_*ich 12

String.formatJava中的方法需要Objects作为其参数.将Object在Java类型等同于AnyRef在斯卡拉类型.Scala中的原始类型扩展AnyVal- 不是AnyRef.了解更多关于的差异之间AnyVal,AnyRef以及Any 在文档这个答案.最明显的解决方法是使用IntegerJava中的包装器类来Object表示您的Ints:

String.format("\\u%04x\\u%04x", new Integer(hi), new Integer(lo))
Run Code Online (Sandbox Code Playgroud)

使用这些包装类几乎是单一的Scala代码的象征,并且只有在没有更好的选择时才应该用于与Java的互操作性.在Scala中执行此操作的更自然的方法是使用StringOps等效方法format:

"\\u%04x\\u%04x".format(hi, lo)
Run Code Online (Sandbox Code Playgroud)

您还可以使用f插值器来获得更简洁的语法:

f"\\u$hi%04x\\u$lo%04x"
Run Code Online (Sandbox Code Playgroud)

此外,使用for像你在这里的循环在Scala中是单一的.你最好不要使用的功能列表的方法,如一个map,foldLeft或者甚至foreach连同使用部分功能match语法.例如,您可以尝试以下方法:

toCodePointArray(input).foreach {
    case x if x > 65535 => 
        val hi = (x - 0x10000) / 0x400 + 0xD800
        val lo = (x - 0x10000) % 0x400 + 0xDC00
        sb.append(f"\\u$hi%04x\\u$lo%04x") 
    case x if > 127 => sb.append(f"\\u$x%04x") 
    case x => sb.append(f"$x%c")    
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您不必使用StringBuilder,实际上只需要在附加许多字符串的情况下使用,您可以用以下内容替换整个方法体foldLeft:

def escapeUnicodeStuff(input: String) = toCodePointArray(input).foldLeft("") {
    case (acc, x) if x > 65535 => 
        val hi = (x - 0x10000) / 0x400 + 0xD800
        val lo = (x - 0x10000) % 0x400 + 0xDC00
        acc + f"\\u$hi%04x\\u$lo%04x"
    case (acc, x) if x > 127 => acc + f"\\u$x%04x"
    case (acc, x) => acc + f"$x%c"
}
Run Code Online (Sandbox Code Playgroud)

或者偶然map后跟一个mkString:

def escapeUnicodeStuff(input: String) = toCodePointArray(input).map {
    case x if x > 65535 => 
        val hi = (x - 0x10000) / 0x400 + 0xD800
        val lo = (x - 0x10000) % 0x400 + 0xDC00
        f"\\u$hi%04x\\u$lo%04x"
    case x if x > 127 => f"\\u$x%04x"
    case x => f"$x%c"
}.mkString
Run Code Online (Sandbox Code Playgroud)