15

文字列を返すメソッドがあります。空の文字列を"<empty>"返す場合やnull. その名前が であると仮定しましょうgetSomeString。これは高価な操作であるため、一度しか呼び出すことができず、戻り値の型を に変更することはできませんOption[String]。今のところ、次のことを行っています。

val myStr = {
  val s = getSomeString
  if (s == null || s.isEmpty) "<empty>" else s
}

同じことを達成するためのより簡単な方法はありますか?

4

6 に答える 6

14

高価な関数が与えられた場合:

scala> def s(i: Int): String = i match { case 0=>null case 1=>"" case 2=>"hi" }
s: (i: Int)String

これは読みやすく、オーバーヘッドがないと思います。これを実際に参照してください。

scala> def q(i: Int) = s(i) match { case ""|null => "<empty>" case x => x }
q: (i: Int)String

scala> q(0)
res3: String = <empty>

scala> q(1)
res4: String = <empty>

scala> q(2)
res5: String = hi

私の目には、最小限の句読点を使用しても、これはそれほど表現的ではありません。

scala> Option(s(0)) filterNot (_.isEmpty) getOrElse "<empty>"
res6: String = <empty>

anonfunさらに、クロージャーと追加のメソッド呼び出しのクラスのコストを比較してください。

scala> :javap -
  Size 1161 bytes
  MD5 checksum 765f5f67b0c574252b059c8adfab1cf0
  Compiled from "<console>"
[...]
         9: getstatic     #26                 // Field scala/Option$.MODULE$:Lscala/Option$;
        12: getstatic     #31                 // Field .MODULE$:L;
        15: iconst_0      
        16: invokevirtual #35                 // Method .s:(I)Ljava/lang/String;
        19: invokevirtual #39                 // Method scala/Option$.apply:(Ljava/lang/Object;)Lscala/Option;
        22: new           #41                 // class $anonfun$1
        25: dup           
        26: invokespecial #42                 // Method $anonfun$1."<init>":()V
        29: invokevirtual #48                 // Method scala/Option.filterNot:(Lscala/Function1;)Lscala/Option;
        32: new           #50                 // class $anonfun$2
        35: dup           
        36: invokespecial #51                 // Method $anonfun$2."<init>":()V
        39: invokevirtual #55                 // Method scala/Option.getOrElse:(Lscala/Function0;)Ljava/lang/Object;
        42: checkcast     #57                 // class java/lang/String
        45: putfield      #17                 // Field res6:Ljava/lang/String;

s == ""パターン マッチは通常、単なる if-else であり、小さくて高速です (最適化されていないことを考慮してもs.isEmpty)。

scala> :javap -r #q
  public java.lang.String q(int);
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=5, args_size=2
         0: getstatic     #19                 // Field $line3/$read$$iw$$iw$.MODULE$:L$line3/$read$$iw$$iw$;
         3: iload_1       
         4: invokevirtual #22                 // Method $line3/$read$$iw$$iw$.s:(I)Ljava/lang/String;
         7: astore_3      
         8: ldc           #24                 // String 
        10: aload_3       
        11: invokevirtual #28                 // Method java/lang/Object.equals:(Ljava/lang/Object;)Z
        14: ifeq          22
        17: iconst_1      
        18: istore_2      
        19: goto          33
        22: aload_3       
        23: ifnonnull     31
        26: iconst_1      
        27: istore_2      
        28: goto          33
        31: iconst_0      
        32: istore_2      
        33: iload_2       
        34: ifeq          44
        37: ldc           #30                 // String <empty>
        39: astore        4
        41: goto          47
        44: aload_3       
        45: astore        4
        47: aload         4
        49: areturn       

しかし、他の答えに触発されて、両親に会うためにこのコードを家に持ち帰らなかったとしても("null"高価な関数が値を返す場合、値を誤って変換するためですが、おそらくそれを行う機能です)、正規表現は次のとおりです。

scala> def p(i: Int) = "" + s(i) replaceAll ("^null$|^$", "<empty>")
p: (i: Int)String

はの"" + s(i)省略形でString.valueOfあり、もちろん"null"null 参照値の文字列を生成します。質問に対する迅速な回答を生成するだけでなく、独創的な考え方を奨励する SO の能力に感謝します。

于 2013-08-24T13:09:02.703 に答える
2

最初のステップでnullを空の文字列に置き換えOption、結果が空の場合はデフォルトのテキストに置き換えることができます(最初に空だったからか、nullだったからか)。

Option(getSomeString).getOrElse("").replaceAll("^$","<empty>")
于 2013-08-24T11:21:02.237 に答える