天天看点

Scala下划线用法总结

作者:散文随风想

1. 变量初始化

在Java中,可以声明变量而不必给出初始值。

class Foo{
     //String类型的默认值为null
     String s;
}           

在Scala中,变量在声明时必须显示指定初始值,可以使用下划线对变量进行初始化。该语法只适用于成员变量,不适用于局部变量。例:

class Foo{
    //String类型的默认值为null
    var s: String = _
}           

对于Int来说, 初始值是0。对于Double来说, 初始值是0.0。对于引用类型, 初始值是null。。。

2. 用于导包引入

导包引入时使用_导入该包下所有内容,类比Java中的*。例如:

//Java
import java.util.*;

//Scala
import java.util._           

3. 用于将方法转变为函数

Scala中方法和函数是两个不同的概念,方法无法作为参数进行传递,也无法赋值给变量,但是函数是可以的。在Scala中,利用下划线可以将方法转换成函数:

def sum(a:Int,b:Int): Int ={
    a + b
  }
  def main(args: Array[String]): Unit = {
    val s = sum _
    println(s)
    println(s(2,4))
  }           

4. 变长参数

向函数或方法传入变长参数时不能直接传入Range或集合或数组对象,需要使用:_*转换才可传入

def sum(args : Int *): Int ={
    var result = 0
    args.foreach(x => {
      result += x
    })
    result
  }
  def main(args: Array[String]): Unit = {
    val s = sum(2,3) //允许
    val s1 = sum(2 to 4 : _* ) //这种情况必须在后面写上: _* 将2 to 4转化为参数序列
    println(s)
    println(s1)
  }           

5. 模式匹配

模式匹配中可以用下划线来作为Java中default的类使用,也可以在匹配集合类型时,用于代表集合中元素,例:

println("匹配常量===")
    val str = "a"
    str match {
      case "a" => println("match a")
      case _ => println("match default")
    }


    println("匹配类型===")
    val x:Any = 12
    x match {
      case s:String => println("match String")
      case i:Int => println("match Int")
      case _ => println("match default")
    }


    println("匹配以0开头,长度为3的列表===")
    val list = List(0,2,3)
    list match {
      case List(0,_,_) => println("found list")
      case _ =>
    }


    println("匹配以0开头,任意长度的列表===")
    list match {
      case List(0,_*) => println("found list")
      case _ =>
    }


    println("变量声明中的模式匹配===")
    val arr = Array(1,2,3,4,5)
    val Array(first, second, _*) = arr   //分别将arr中的第一个和第二个值赋给first和second
    println(s"first:$first,second:$second")
           

6. 用于访问tuple元素

val t = (1,2,3)
    println(t._1)           

7. 用于简写函数

如果函数的参数在函数体内只出现一次,则可以使用下划线代替:

val list = List(1,2,3,4)

    list.foreach(println(_))
    //等价于
    list.foreach(x => println(x))

    list.filter(_ > 1)
    //等价于
    list.filter(x => x > 1)

    val sum1 = (x:Int,y:Int) => x + y
    //等价于
    val sum2 = (_:Int) + (_:Int)           

8. 类型通配符

Java的泛型系统有一个通配符类型,例如List<?>,任意的List<T>类型都是List<?>的子类型,如果我们想编写一个可以打印所有List类型元素的方法,可以如下声明:

public static void printList(List<?> list){
        list.forEach(System.out::println);
    }           

对应的Scala版本为:

def printList(list: List[_]): Unit ={
    list.foreach(println)
  }           

9. 定义偏函数

对某个多参数函数进行部分函数调用,没有传入的参数使用_代替,返回结果即为偏函数。例:

def sum(a:Int,b:Int): Int ={
    a + b
  }
  def main(args: Array[String]): Unit = {
    val s = sum(1 , _:Int)  //s就是偏函数,绑定第一个 a 参数,第二个参数使用下划线 _ 替换缺失的参数列表
    println(s(2))
  }