`

Scala 下划线(_)的多种应用场景学习

 
阅读更多
1、作为“通配符”,类似Java中的*。如import scala.math._

2、:_*作为一个整体,告诉编译器你希望将某个参数当作参数序列处理!例如val s = sum(1 to 5:_*)就是将1 to 5当作参数序列处理。

3、指代一个集合中的每个元素。例如我们要在一个Array a中筛出偶数,并乘以2,可以用以下办法:a.filter(_%2==0).map(2*_)。又如要对缓冲数组ArrayBuffer b排序,可以这样:val bSorted = b.sorted(_)

4、在元组中,可以用方法_1, _2, _3访问组员。如a._2。其中句点可以用空格替代。

5、使用模式匹配可以用来获取元组的组员,例如val (first, second, third) = t但如果不是所有的部件都需要,那么可以在不需要的部件位置上使用_。比如上一例中val (first, second, _) = t

6、还有一点,下划线_代表的是某一类型的默认值。对于Int来说,它是0。对于Double来说,它是0.0对于引用类型,它是null。


下划线这个符号几乎贯穿了任何一本Scala编程书籍,并且在不同的场景下具有不同的含义,绕晕了不少初学者。正因如此,下划线这个特殊符号无形中增加Scala的入门难度。本文希望帮助初学者踏平这个小山坡。

1. 用于替换Java的等价语法

由于大部分的Java关键字在Scala中拥有了新的含义,所以一些基本的语法在Scala中稍有变化。

1.1 导入通配符

*在Scala中是合法的方法名,所以导入包时要使用_代替。

//Java
import java.util.*;

//Scala
import java.util._


1.2 类成员默认值

Java中类成员可以不赋初始值,编译器会自动帮你设置一个合适的初始值:

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

而在Scala中必须要显式指定,如果你比较懒,可以用_让编译器自动帮你设置初始值:

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

该语法只适用于类成员,而不适用于局部变量。

1.3 可变参数

Java声明可变参数如下:

public static void printArgs(String ... args){
    for(Object elem: args){
        System.out.println(elem + " ");
    }
}

调用方法如下:

//传入两个参数
printArgs("a", "b");
//也可以传入一个数组
printArgs(new String[]{"a", "b"});

在Java中可以直接将数组传给printArgs方法,但是在Scala中,你必须要明确的告诉编译器,你是想将集合作为一个独立的参数传进去,还是想将集合的元素传进去。如果是后者则要借助下划线:

printArgs(List("a", "b"): _*)


1.4 类型通配符
Java的泛型系统有一个通配符类型,例如List<?>,任意的List<T>类型都是List<?>的子类型,如果我们想编写一个可以打印所有List类型元素的方法,可以如下声明:
public static void printList(List<?> list){
    for(Object elem: list){
        System.out.println(elem + " ");
    }
}

对应的Scala版本为:

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


2 模式匹配

2.1 默认匹配

str match{
    case "1" => println("match 1")
    case _   => println("match default")
}
[b]2.2 匹配集合元素[/b]

//匹配以0开头,长度为三的列表
expr match {
  case List(0, _, _) => println("found it")
  case _ =>
}

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

//匹配元组元素
expr match {
  case (0, _) => println("found it")
  case _ =>
}

//将首元素赋值给head变量
val List(head, _*) = List("a")


3. Scala特有语法

3.1 访问Tuple元素

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


3.2 简写函数字面量(function literal)

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

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

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

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


3.3 定义一元操作符

在Scala中,操作符其实就是方法,例如1 + 1等价于1.+(1),利用下划线我们可以定义自己的左置操作符,例如Scala中的负数就是用左置操作符实现的:

-2
//等价于
2.unary_-
3.4 定义赋值操作符

我们通过下划线实现赋值操作符,从而可以精确地控制赋值过程:

class Foo {
      def name = { "foo" }
      def name_=(str: String) {
        println("set name " + str)
   }

    val m = new Foo()
    m.name = "Foo" //等价于: m.name_=("Foo")

3.5 定义部分应用函数(partially applied function)

我们可以为某个函数只提供部分参数进行调用,返回的结果是一个新的函数,即部分应用函数。因为只提供了部分参数,所以部分应用函数也因此而得名。

def sum(a: Int, b: Int, c: Int) = a + b + c
val b = sum(1, _: Int, 3)
b: Int => Int = <function1>
b(2) //6


3.6 将方法转换成函数

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

//将println方法转换成函数,并赋值给p
val p = println _  
//p: (Any) => Unit


转自:https://my.oschina.net/joymufeng/blog/863823
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    jupyter-Scala_2.11.11_kernel_Windows.zip

    "jupyter-Scala_2.11.11_kernel_Windows.zip" 是专为Windows操作系统设计的Jupyter Notebook Scala内核安装包,允许用户在Jupyter环境中编写和运行Scala代码。 Scala是一种多范式编程语言,结合了面向对象和函数式...

    flink-scala_2.12-1.14.3-API文档-中文版.zip

    赠送jar包:flink-scala_2.12-1.14.3.jar 赠送原API文档:flink-scala_2.12-1.14.3-javadoc.jar 赠送源代码:flink-scala_2.12-1.14.3-sources.jar 包含翻译后的API文档:flink-scala_2.12-1.14.3-javadoc-API...

    Scala_中文学习资料_含Scala_2.7.6_API.rar

    这个压缩包文件"Scala_中文学习资料_含Scala_2.7.6_API.rar"显然是为那些希望深入理解Scala编程的人准备的,特别是对于中文使用者,因为其中包含了一些中文文档。 首先,"Scala_2.7.6_API.chm"是一个帮助文件,通常...

    scalatest_2.10-2.1.1.zip

    在实际应用中,Scalatest可以帮助开发者进行单元测试、集成测试以及功能测试,通过定义测试套件和测试用例,可以有效地检查代码的功能和性能。而nv-digest库则可以在需要验证数据完整性、比较文件是否相同或创建安全...

    flink-1.9.1-bin-scala_2.11.tgz

    flink-1.9.1-bin-scala_2.11.tgz flink-1.9.1-bin-scala_2.11.tgz flink-1.9.1-bin-scala_2.11.tgz flink-1.9.1-bin-scala_2.11.tgz

    SVM.zip_hadoop SVM_hadoop svm_scala_scala 分类_svm scala

    在"scala_分类"这个标签中,我们看到使用Scala编程语言来实现SVM。Scala是一种静态类型的编程语言,它结合了面向对象和函数式编程的特性,非常适合用于开发大规模数据处理应用,如Spark。 具体实现过程中,"SVMMain...

    scalatest_2.11-2.2.1.jar

    ScalatestDotty org.scalatest/scalatest_2.11/2.2.1/scalatest_2.11-2.2.1.jar

    jackson-module-scala_2.11-2.6.7.1-API文档-中英对照版.zip

    赠送jar包:jackson-module-scala_2.11-2.6.7.1.jar; 赠送原API文档:jackson-module-scala_2.11-2.6.7.1-javadoc.jar; 赠送源代码:jackson-module-scala_2.11-2.6.7.1-sources.jar; 赠送Maven依赖信息文件:...

    Play for Scala.pdf_several7zb_scala_play_play开发scalaweb_

    Play Framework是一種用Scala編寫的Web應用框架,其遵循模型-視圖-控制器建築模式。Play Framework使用Scala編寫,並可以被編譯成Java虛擬機器位元組碼中的其他編程語言使用;例如Java語言。

    scala-xml_2.12-1.0.6-API文档-中文版.zip

    赠送jar包:scala-xml_2.12-1.0.6.jar; 赠送原API文档:scala-xml_2.12-1.0.6-javadoc.jar; 赠送源代码:scala-xml_2.12-1.0.6-sources.jar; 赠送Maven依赖信息文件:scala-xml_2.12-1.0.6.pom; 包含翻译后的API...

    Apache Flink(flink-1.14.4-bin-scala_2.12.tgz)

    Apache Flink(flink-1.14.4-bin-scala_2.12.tgz)是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。Flink以数据并行和流水线方式执行任意流数据程序,Flink的流水线运行...

    flink-1.12.0-bin-scala_2.12.tgz

    标题中的"flink-1.12.0-bin-scala_2.12.tgz"指的是一款基于Apache Flink 1.12.0版本的二进制发行版,适用于Scala 2.12环境的压缩包。这个压缩文件采用TGZ(tar.gz)格式,是一种常见的Linux/Unix下的归档压缩方式,...

    flink-1.12.7-bin-scala_2.12.tgz

    这个压缩包 "flink-1.12.7-bin-scala_2.12.tgz" 包含了 Flink 1.12.7 的二进制版本,特别针对使用 Scala 2.12 的开发环境进行了优化。 1. **Flink 的核心特性** - **流处理**:Flink 提供了一种无界限数据的概念,...

    flink-1.13.6-bin-scala_2.12.tgz资源下载

    总的来说,`flink-1.13.6-bin-scala_2.12.tgz` 是一个全面的 Flink 发行版,适合开发者用于构建和部署实时数据处理应用,利用 Scala 语言的强大功能和 Flink 的高效流处理能力。无论你是刚接触 Flink 还是已经有一定...

    flink-1.15.1-bin-scala_2.12.tgz

    flink-1.15.1-bin-scala_2.12.tgz

    flink-1.14.0-bin-scala_2.11.tgz

    首先,我们来看看标题“flink-1.14.0-bin-scala_2.11.tgz”,这表明这是一个针对 Scala 2.11 的 Flink 1.14.0 安装包。Scala 是一种多范式编程语言,广泛用于构建分布式系统,特别是大数据处理框架。它与 Flink 的...

    Scala_2.7.6_API.chm.7z

    这个压缩包文件"Scala_2.7.6_API.chm.7z"包含了Scala 2.7.6版本的API文档,这是一份重要的参考资料,帮助开发者理解和使用Scala语言及其库。 Scala API文档详细介绍了各种内置类、对象、模块和语言特性。以下是其中...

    flink-1.14.4-scala_2.12 + CDH6.2.1 版 parcel 包

    flink-1.14.4-scala_2.12 + CDH6.2.1 版 parcel 包, 包含 FLINK-1.14.4-BIN-SCALA_2.12-el7.parcel FLINK-1.14.4-BIN-SCALA_2.12-el7.parcel.sha manifest.json (以上三个文件放入 /opt/cloudera/parcel-repo/ 下...

    flink-1.12.0-bin-scala_2.11.tgz

    总的来说,"flink-1.12.0-bin-scala_2.11.tgz"是一个完整的Apache Flink发行版,包含了运行和开发Flink应用所需的所有组件。用户可以通过解压此文件,在Scala 2.11环境中配置和运行Flink作业,实现高效的数据处理。

Global site tag (gtag.js) - Google Analytics