Scala 中的foreach和map方法比较

转自:https://www.cnblogs.com/1zhk/p/4710580.html      https://blog.youkuaiyun.com/u010454030/article/details/53899587

Scala中的集合对象都有foreach和map两个方法。两个方法的共同点在于:都是用于遍历集合对象,并对每一项执行指定的方法。而两者的差异在于:foreach无返回值(准确说返回void),map返回集合对象。见如下代码及运行结果:b.getClass 得到的是void, 而c.getClass得到的是colletion 。再看代码的第9-11行,foreach和map的运行结果一致。结论就是:foreach 无法代替map. 而map方法却可以代替foreach。

问题:为什么scala提供foreach和map两个方法呢?本人看法是scala做为一种支持函数式编程范式的语言,必然要引入一种机制以支持数学中函数概念,而在数学中函数就是映射,所以scala中有map方法一点都不奇怪。而foreach只是用在不需要对集合执行映射操作,但需要遍历集合时才用到。总而言之,foreach用于遍历集合,而map用于映射(转换)集合到另一个集合。

 

复制代码
 1 object arrayTest extends App{
 2   var increase=(x:Int)=>x+1
 3   val someNumbers = List ( -11, -10, - 5, 0, 5, 10)
 4   var b = someNumbers.foreach(increase)
 5   println(b.getClass)
 6   var c = someNumbers.map(increase)
 7   println(c.getClass)
 8 
 9   c.foreach((x:Int)=>print(x+" "))
10   println()
11   c.map((x:Int)=>print(x+" "))
12 
13 }
复制代码

运行结果:


(1)不可变Map

特点:

api不太丰富

如果是var修饰,引用可变,支持读写

如果是val修饰,引用不可变,只能写入一次值,其后只读

var a:Map[String,Int]=Map("k1"->1,"k2"->2)//初始化构造函数
    a += ("k3"->3)//添加元素
    a += ("k4"->4)//添加元素
    a += ("k1"->100)//已经存在添加元素会覆盖
    a -= ("k2","k1")//删除元素
//    a("k1") = "foo"//不支持
    println(a.contains("k6"))//是否包含某元素
    println(a.size)//打印大小
    println(a.get("k1").getOrElse("default")) //根据key读取元素,不存在就替换成默认值
    a.foreach{case (e,i) => println(e,i)} //遍历打印1
    for( (k,v)<-a ) println(k,v) //遍历打印2
    println(a.isEmpty)//判断是否为空
    a.keys.foreach(println)//只打印key
    a.values.foreach(println)//只打印value
    a=Map()//数据清空使用再次new
    println(a.size)
    a.toSeq.sortBy(_._1)//升序排序 key
    a.toSeq.sortBy(_._2)//升序排序 value
    a.toSeq.sortWith(_._1>_._1) //降序排序 key
    a.toSeq.sortWith(_._2>_._2) //降序排序 value
    
    //下面自定义按英文字母或数字排序
    implicit  val KeyOrdering=new Ordering[String] {
      override def compare(x: String, y: String): Int = {
        x.compareTo(y)
      }
    }
    println(a.toSeq.sorted)
(2)可变Map例子

特点:

api丰富与Java中Map基本类似

如果是var修饰,引用可变,支持读写

如果是val修饰,引用不可变,支持读写

def map3(): Unit ={
  //不可变Map+var关键词修饰例子
  var a:scala.collection.mutable.Map[String,Int]=scala.collection.mutable.Map("k1"->1,"k2"->2)//初始化构造函数
  a += ("k3"->3)//添加元素
  a += ("k4"->4)//添加元素
  a += ("k1"->100)//已经存在添加元素会覆盖
  a += ("k1"->100,"k9"->9)//添加多个元素
  a -= ("k2","k1")//删除元素
  a ++= List("CA" -> 23, "CO" -> 25)//追加集合
  a --= List("AL", "AZ")//删除集合

  a.retain((k,v)=> k=="k1")//只保留等于k1元素,其他的删除
  a.put("put1",200)//put
  a.remove("k2")//remove
  a.clear()//清空
  a("k3")=100//支持

  println(a.contains("k6"))//是否包含某元素
  println(a.size)//打印大小
  println(a.get("k1").getOrElse("default")) //根据key读取元素,不存在就替换成默认值
  a.foreach{case (e,i) => println(e,i)} //遍历打印1
  for( (k,v)<-a ) println(k,v) //遍历打印2
  println(a.isEmpty)//判断是否为空
  a.keys.foreach(println)//只打印key
  a.values.foreach(println)//只打印value
  a=scala.collection.mutable.Map()//引用能变
  println(a.size)
  a.toSeq.sortBy(_._1)//排序 key
  a.toSeq.sortBy(_._2)//排序 value
  a.toSeq.sortWith(_._1>_._1) //降序排序 key
  a.toSeq.sortWith(_._2>_._2) //降序排序 value
  
      //下面自定义按英文字母或数字排序
  implicit  val KeyOrdering=new Ordering[String] {
    override def compare(x: String, y: String): Int = {
      x.compareTo(y)
    }
  }
  println(a.toSeq.sorted)
}




<think>好的,用户想了解Scala中函数方法的区别以及如何定义。首先,我需要回忆Scala的基础知识,确保信息准确。记得函数方法Scala中是不同的概念,但有时候容易混淆。 首先,方法的定义是使用def关键字,属于类、特质或对象的一部分,通常与面向对象编程相关。而函数是一个独立的代码块,可以赋值给变量,作为参数传递或作为返回值,是一等公民。这点需要明确区分。 接下来,应该从定义方式入手。比如,方法需要在类或对象中定义,而函数可以通过lambda表达式或FunctionN的实例来创建。例如,方法可能有参数列表返回类型,而函数可以作为变量存储。 然后,作用域也是一个区别点。方法在类或对象内部定义,而函数可以在任何地方定义,包括另一个函数内部。比如,用户提供的引用[2]中的例子,函数sayHello定义在main方法内部,这说明函数可以在方法内定义。 调用方式的不同也需要说明。方法调用依赖于对象实例,而函数可以直接调用或传递。此外,方法可以转换成函数,比如通过方法名加空格下划线的方式,如method _,这样可以将方法提升为函数。 关于定义示例,用户给的引用[2]中的代码展示了在对象内部定义方法函数的情况。比如,main方法中定义了函数sayHello,而方法可能定义在类或对象的结构体中。需要分别给出方法函数的定义例子,比如在对象中定义一个方法,以及在方法内部或外部定义一个函数。 可能还需要提到,函数可以作为参数传递给高阶函数,如map、filter等,而方法需要先转换成函数才能使用。这点对于理解函数式编程在Scala中的应用很重要。 用户的问题还可能涉及它们的使用场景,比如在函数式编程中更常用函数,而在面向对象中更常用方法。但Scala是混合范式,所以两者都可以灵活使用。 需要检查是否有遗漏的点,比如类型推断、参数列表的差异。例如,方法可以有多参数列表,而函数的参数必须在一个列表中。此外,方法可以有隐式参数,而函数可能不支持。 最后,确保回答结构清晰,分点说明区别,并提供定义示例。同时,根据用户提供的引用内容,正确引用相关部分,如引用[1]提到函数是一等公民,可以在任何地方定义,作为参数返回值,这点需要强调。而引用[2]中的代码示例展示了函数定义调用的具体方式,应该结合这些例子进行说明。 总结回答的结构:先解释方法函数的定义,然后分点列出区别,包括定义位置、语法、作用域、转换方式等,再给出各自的代码示例,最后总结两者的主要区别应用场景。同时,生成相关问题,帮助用户深入理解。</think>### Scala函数与方法的区别及定义方式 #### 一、定义方式 1. **方法** 使用`def`关键字定义,属于类、特质或对象的成员,具有面向对象特性。 **示例**: ```scala class Calculator { def add(a: Int, b: Int): Int = a + b // 类中定义方法 } ``` 2. **函数** 通过`val`或`var`定义,是独立的值(类型为`FunctionN`),可赋值给变量或作为参数传递[^1]。 **示例**: ```scala val multiply = (a: Int, b: Int) => a * b // 函数赋值给变量 ``` #### 二、核心区别 | 特性 | 方法 | 函数 | |-------------|-------------------------------|-------------------------------| | **定义位置** | 类/对象内部 | 任何地方(包括函数内部)[^2] | | **语法** | `def`关键字 | `=>`箭头表达式 | | **独立性** | 依附于对象 | 一等公民,可独立存在[^1] | | **参数列表** | 支持多参数列表(柯里化) | 单参数列表 | | **转换方式** | 可通过`方法名 _`转为函数 | 无需转换直接使用 | #### 三、代码示例对比 1. **方法定义与调用** ```scala object MathUtils { def square(x: Int): Int = x * x // 对象中的方法 } MathUtils.square(5) // 输出25 ``` 2. **函数定义与传递** ```scala val greet: String => Unit = (name: String) => println(s"Hello, $name") List("Alice", "Bob").foreach(greet) // 函数作为参数传递 ``` 3. **方法转函数** ```scala def methodToFunction(x: Int): Int = x * 2 val func = methodToFunction _ // 方法转为函数 func(3) // 输出6 ``` #### 四、核心总结 - **方法**是面向对象的基本单元,**函数**是函数式编程的核心。 - 函数可灵活用于高阶操作(如`map`、`filter`),方法需转换后才能使用。 - 方法支持更复杂的语法(如柯里化),函数更轻量级。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值