这个Scala部分函数是如何工作的? //首先使用常规字典查找 def findElement(e:String,dict:Map[String,Any]):Option[Any]=dict.get(e)
; //第二,使用部分函数 def findElement(e:String,dict:Map[String,Any]):Option[Any]=dict.find{case(k,v)=>k==e}Map(u.\u 2)


这个Scala部分函数是如何工作的? //首先使用常规字典查找 def findElement(e:String,dict:Map[String,Any]):Option[Any]=dict.get(e)
; //第二,使用部分函数 def findElement(e:String,dict:Map[String,Any]):Option[Any]=dict.find{case(k,v)=>k==e}Map(u.\u 2)
,scala,functional-programming,Scala,Functional Programming,它们给出了相同的答案,但是,第二个函数是如何工作的呢 使用case关键字的分部函数的BigO是什么?它是否迭代地图的所有元素以找到正确的键?您需要知道的一些事情: Map[A,B]也是一个PartialFunction[A,B] 部分函数具有lift方法,将其转换为a=>选项[B]-get基本上变成apply.lift Map也可以被视为成对的序列(Seq[(A,B)])-当您Map、flatMap、收集、查找等时可以看到它 find是一个返回集合的第一个元素的函数(在Map的情况下,它是一对

它们给出了相同的答案,但是,第二个函数是如何工作的呢


使用case关键字的分部函数的BigO是什么?它是否迭代地图的所有元素以找到正确的键?

您需要知道的一些事情:

  • Map[A,B]
    也是一个
    PartialFunction[A,B]
  • 部分函数具有
    lift
    方法,将其转换为
    a=>选项[B]
    -
    get
    基本上变成
    apply.lift
  • Map
    也可以被视为成对的序列(
    Seq[(A,B)]
    )-当您
    Map
    flatMap
    收集
    查找
    等时可以看到它
  • find
    是一个返回集合的第一个元素的函数(在
    Map
    的情况下,它是一对)-如果集合中没有这样的元素,则
    None
    处理该元素
  • {case(k,v)=>}
    使用模式匹配从元组中提取值,并将其放入值
    k
    v
  • 。\u 2
    是一种元组方法(返回第二个值)
考虑到这一点:

dict.get(e)

是。。。非常明显-返回
e
键的值,如果存在,则将其包装在
Some
中,否则,返回
None
apply
将抛出缺少的值)


它将试图找到
k==e
的第一个元素,返回
Option[(字符串,任意)]
,然后使用
map
通过将整个元组转换为第二个值来转换
Option
(如果存在)中的值。

编辑:OP编辑了他们的问题,删除了对“部分应用函数”的引用因此,这些章节不再相关。不过我还是把它们留在这里,因为如果有人把它们混在一起可能会很有价值

这不是一个部分应用的函数,而是一个PartialFunction()

部分应用的函数是具有多个参数的函数,您只提供了其中的一部分,您可以将部分应用的函数交给其他人来提供其余的参数

部分函数在文档中定义为:

PartialFunction[A,B]类型的分部函数是一元函数,其中域不一定包括A类型的所有值。函数定义为允许动态测试值是否在函数域中

您提供的案例应该涵盖所有案例,因为您的域都是
Tuple2
s,因为您没有防范特定的值,但它不会强迫您在PartialFunction中涵盖所有案例

dict.get(e)
=O(1)或最多O(N)取决于Map处理冲突的方式或哈希代码的分布方式
dict.find{case(k,v)=>k==e}map(u._2)
=O(N)由于.find实现。如果我们深入研究方法查找实现,我们将看到:

override /*TraversableLike*/ def find(p: A => Boolean): Option[A] =
    iterator.find(p)
然后更深入:

  def find(p: A => Boolean): Option[A] = {
    while (hasNext) {
      val a = next()
      if (p(a)) return Some(a)
    }
    None
  }
这里我们可以看到,当循环遍历迭代器中的所有元素时,直到传递的函数
p:A=>Boolean
返回true。这里有max N迭代

我不是那么懒,而是使用sbt jmh编写了一个基准测试:

import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations.{Benchmark, OutputTimeUnit, Scope, State}

@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
class FindElementBenchmark {

  val dict: Map[String, Any] =
    (0 to 100).foldLeft(Map.empty[String, Any])((m, i) => m + (s"key$i" ->s"value$i"))

  val e: String = "key99"

  // First using normal dictionary lookup
  @Benchmark
  def findElementDict: Option[Any] =
    dict.get(e)

  // Second using Partial function
  @Benchmark
  def findElementPF: Option[Any] =
    dict
      .find { case (k, v) => k == e }
      .map(_._2)
}
运行它:

$ sbt
$ sbt:benchmarks> jmh:run -i 20 -wi 10 -f1 -t1
并取得了以下成果:

[info] Running (fork) org.openjdk.jmh.Main -i 20 -wi 10 -f1 -t1
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_161, Java HotSpot(TM) 64-Bit Server VM, 25.161-b12
[info] # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 10 iterations, 10 s each
[info] # Measurement: 20 iterations, 10 s each
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread, will synchronize iterations
[info] # Benchmark mode: Throughput, ops/time
[info] # Benchmark: bmks.FindElementBenchmark.findElementDict
[info] # Run progress: 0.00% complete, ETA 00:10:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration   1: 48223.037 ops/ms
[info] # Warmup Iteration   2: 48570.873 ops/ms
[info] # Warmup Iteration   3: 48730.899 ops/ms
[info] # Warmup Iteration   4: 45050.838 ops/ms
[info] # Warmup Iteration   5: 48191.539 ops/ms
[info] # Warmup Iteration   6: 48464.603 ops/ms
[info] # Warmup Iteration   7: 48690.140 ops/ms
[info] # Warmup Iteration   8: 46432.571 ops/ms
[info] # Warmup Iteration   9: 46772.835 ops/ms
[info] # Warmup Iteration  10: 47214.496 ops/ms
[info] Iteration   1: 49149.297 ops/ms
[info] Iteration   2: 48476.424 ops/ms
[info] Iteration   3: 48590.436 ops/ms
[info] Iteration   4: 48214.015 ops/ms
[info] Iteration   5: 48698.636 ops/ms
[info] Iteration   6: 48686.357 ops/ms
[info] Iteration   7: 48948.054 ops/ms
[info] Iteration   8: 48917.577 ops/ms
[info] Iteration   9: 48872.980 ops/ms
[info] Iteration  10: 48970.421 ops/ms
[info] Iteration  11: 46269.031 ops/ms
[info] Iteration  12: 44934.335 ops/ms
[info] Iteration  13: 46279.314 ops/ms
[info] Iteration  14: 47721.223 ops/ms
[info] Iteration  15: 46238.490 ops/ms
[info] Iteration  16: 47453.282 ops/ms
[info] Iteration  17: 47886.762 ops/ms
[info] Iteration  18: 48032.580 ops/ms
[info] Iteration  19: 48142.064 ops/ms
[info] Iteration  20: 48460.665 ops/ms
[info] Result "bmks.FindElementBenchmark.findElementDict":
[info]   47947.097 ±(99.9%) 1003.440 ops/ms [Average]
[info]   (min, avg, max) = (44934.335, 47947.097, 49149.297), stdev = 1155.563
[info]   CI (99.9%): [46943.657, 48950.537] (assumes normal distribution)
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_161, Java HotSpot(TM) 64-Bit Server VM, 25.161-b12
[info] # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 10 iterations, 10 s each
[info] # Measurement: 20 iterations, 10 s each
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread, will synchronize iterations
[info] # Benchmark mode: Throughput, ops/time
[info] # Benchmark: bmks.FindElementBenchmark.findElementPF
[info] # Run progress: 50.00% complete, ETA 00:05:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration   1: 7261.136 ops/ms
[info] # Warmup Iteration   2: 7548.525 ops/ms
[info] # Warmup Iteration   3: 7517.692 ops/ms
[info] # Warmup Iteration   4: 7126.543 ops/ms
[info] # Warmup Iteration   5: 7732.285 ops/ms
[info] # Warmup Iteration   6: 7525.456 ops/ms
[info] # Warmup Iteration   7: 7739.055 ops/ms
[info] # Warmup Iteration   8: 7555.671 ops/ms
[info] # Warmup Iteration   9: 7624.464 ops/ms
[info] # Warmup Iteration  10: 7527.114 ops/ms
[info] Iteration   1: 7631.426 ops/ms
[info] Iteration   2: 7607.643 ops/ms
[info] Iteration   3: 7636.029 ops/ms
[info] Iteration   4: 7413.881 ops/ms
[info] Iteration   5: 7726.417 ops/ms
[info] Iteration   6: 7410.291 ops/ms
[info] Iteration   7: 7452.339 ops/ms
[info] Iteration   8: 7825.050 ops/ms
[info] Iteration   9: 7801.677 ops/ms
[info] Iteration  10: 7783.978 ops/ms
[info] Iteration  11: 7788.909 ops/ms
[info] Iteration  12: 7778.982 ops/ms
[info] Iteration  13: 7784.158 ops/ms
[info] Iteration  14: 7771.173 ops/ms
[info] Iteration  15: 7750.280 ops/ms
[info] Iteration  16: 7813.570 ops/ms
[info] Iteration  17: 7845.550 ops/ms
[info] Iteration  18: 7841.003 ops/ms
[info] Iteration  19: 7808.576 ops/ms
[info] Iteration  20: 7847.100 ops/ms
[info] Result "bmks.FindElementBenchmark.findElementPF":
[info]   7715.902 ±(99.9%) 124.303 ops/ms [Average]
[info]   (min, avg, max) = (7410.291, 7715.902, 7847.100), stdev = 143.148
[info]   CI (99.9%): [7591.598, 7840.205] (assumes normal distribution)
[info] # Run complete. Total time: 00:10:01
[info] REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
[info] why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
[info] experiments, perform baseline and negative tests that provide experimental control, make sure
[info] the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
[info] Do not assume the numbers tell you what you want them to tell.
[info] Benchmark                              Mode  Cnt      Score      Error   Units
[info] FindElementBenchmark.findElementDict  thrpt   20  47947.097 ± 1003.440  ops/ms
[info] FindElementBenchmark.findElementPF    thrpt   20   7715.902 ±  124.303  ops/ms
[success] Total time: 603 s, completed Apr 30, 2019 7:33:10 PM

[info]Running(fork)org.openjdk.jmh.Main-i20-wi10-f1-t1
[信息]#JMH版本:1.21
[信息]#虚拟机版本:JDK 1.8.0_161,Java HotSpot(TM)64位服务器虚拟机,25.161-b12
[信息]#虚拟机调用程序:/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/Java
[信息]#虚拟机选项:
[信息]#预热:10次迭代,每次10秒
[信息]#测量:20次迭代,每次10秒
[信息]#超时:每次迭代10分钟
[信息]#线程:1个线程,将同步迭代
[信息]#基准模式:吞吐量、运营/时间
[信息]#基准:bmks.FindElementBenchmark.findElementDict
[信息]#运行进度:完成0.00%,预计时间00:10:00
[信息]#Fork:1/1
[信息]#预热迭代1:48223.037 ops/ms
[信息]#预热迭代2:48570.873 ops/ms
[信息]#预热迭代3:48730.899 ops/ms
[信息]#预热迭代4:45050.838 ops/ms
[信息]#预热迭代5:48191.539 ops/ms
[信息]#预热迭代6:48464.603操作/毫秒
[信息]#预热迭代7:48690.140 ops/ms
[信息]#预热迭代8:46432.571 ops/ms
[信息]#预热迭代9:46772.835 ops/ms
[信息]#预热迭代10:47214.496 ops/ms
[信息]迭代1:49149.297 ops/ms
[信息]迭代2:48476.424操作/毫秒
[信息]迭代3:48590.436操作/毫秒
[信息]迭代4:48214.015 ops/ms
[信息]迭代5:48698.636 ops/ms
[信息]迭代6:48686.357操作/毫秒
[信息]迭代7:48948.054 ops/ms
[信息]迭代8:48917.577 ops/ms
[信息]迭代9:48872.980 ops/ms
[信息]迭代10:48970.421 ops/ms
[信息]迭代11:46269.031 ops/ms
[信息]迭代12:44934.335 ops/ms
[信息]迭代13:46279.314 ops/ms
[信息]迭代14:47721.223 ops/ms
[信息]迭代15:46238.490 ops/ms
[信息]迭代16:47453.282 ops/ms
[信息]迭代17:47886.762 ops/ms
[信息]迭代18:48032.580次/秒
[信息]迭代19:48142.064 ops/ms
[信息]迭代20:48460.665 ops/ms
[信息]结果“bmks.FindElementBenchmark.findElementDict”:
[信息]47947.097±(99.9%)1003.440次/秒[平均]
[信息](最小值、平均值、最大值)=(44934.335、47947.097、49149.297),标准差=1155.563
[信息]CI(99.9%):[46943.65748950.537](假设为正态分布)
[信息]#JMH版本:1.21
[信息]#虚拟机版本:JDK 1.8.0_161,Java HotSpot(TM)64位服务器虚拟机,25.161-b12
[信息]#虚拟机调用程序:/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Con
[info] Running (fork) org.openjdk.jmh.Main -i 20 -wi 10 -f1 -t1
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_161, Java HotSpot(TM) 64-Bit Server VM, 25.161-b12
[info] # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 10 iterations, 10 s each
[info] # Measurement: 20 iterations, 10 s each
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread, will synchronize iterations
[info] # Benchmark mode: Throughput, ops/time
[info] # Benchmark: bmks.FindElementBenchmark.findElementDict
[info] # Run progress: 0.00% complete, ETA 00:10:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration   1: 48223.037 ops/ms
[info] # Warmup Iteration   2: 48570.873 ops/ms
[info] # Warmup Iteration   3: 48730.899 ops/ms
[info] # Warmup Iteration   4: 45050.838 ops/ms
[info] # Warmup Iteration   5: 48191.539 ops/ms
[info] # Warmup Iteration   6: 48464.603 ops/ms
[info] # Warmup Iteration   7: 48690.140 ops/ms
[info] # Warmup Iteration   8: 46432.571 ops/ms
[info] # Warmup Iteration   9: 46772.835 ops/ms
[info] # Warmup Iteration  10: 47214.496 ops/ms
[info] Iteration   1: 49149.297 ops/ms
[info] Iteration   2: 48476.424 ops/ms
[info] Iteration   3: 48590.436 ops/ms
[info] Iteration   4: 48214.015 ops/ms
[info] Iteration   5: 48698.636 ops/ms
[info] Iteration   6: 48686.357 ops/ms
[info] Iteration   7: 48948.054 ops/ms
[info] Iteration   8: 48917.577 ops/ms
[info] Iteration   9: 48872.980 ops/ms
[info] Iteration  10: 48970.421 ops/ms
[info] Iteration  11: 46269.031 ops/ms
[info] Iteration  12: 44934.335 ops/ms
[info] Iteration  13: 46279.314 ops/ms
[info] Iteration  14: 47721.223 ops/ms
[info] Iteration  15: 46238.490 ops/ms
[info] Iteration  16: 47453.282 ops/ms
[info] Iteration  17: 47886.762 ops/ms
[info] Iteration  18: 48032.580 ops/ms
[info] Iteration  19: 48142.064 ops/ms
[info] Iteration  20: 48460.665 ops/ms
[info] Result "bmks.FindElementBenchmark.findElementDict":
[info]   47947.097 ±(99.9%) 1003.440 ops/ms [Average]
[info]   (min, avg, max) = (44934.335, 47947.097, 49149.297), stdev = 1155.563
[info]   CI (99.9%): [46943.657, 48950.537] (assumes normal distribution)
[info] # JMH version: 1.21
[info] # VM version: JDK 1.8.0_161, Java HotSpot(TM) 64-Bit Server VM, 25.161-b12
[info] # VM invoker: /Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home/jre/bin/java
[info] # VM options: <none>
[info] # Warmup: 10 iterations, 10 s each
[info] # Measurement: 20 iterations, 10 s each
[info] # Timeout: 10 min per iteration
[info] # Threads: 1 thread, will synchronize iterations
[info] # Benchmark mode: Throughput, ops/time
[info] # Benchmark: bmks.FindElementBenchmark.findElementPF
[info] # Run progress: 50.00% complete, ETA 00:05:00
[info] # Fork: 1 of 1
[info] # Warmup Iteration   1: 7261.136 ops/ms
[info] # Warmup Iteration   2: 7548.525 ops/ms
[info] # Warmup Iteration   3: 7517.692 ops/ms
[info] # Warmup Iteration   4: 7126.543 ops/ms
[info] # Warmup Iteration   5: 7732.285 ops/ms
[info] # Warmup Iteration   6: 7525.456 ops/ms
[info] # Warmup Iteration   7: 7739.055 ops/ms
[info] # Warmup Iteration   8: 7555.671 ops/ms
[info] # Warmup Iteration   9: 7624.464 ops/ms
[info] # Warmup Iteration  10: 7527.114 ops/ms
[info] Iteration   1: 7631.426 ops/ms
[info] Iteration   2: 7607.643 ops/ms
[info] Iteration   3: 7636.029 ops/ms
[info] Iteration   4: 7413.881 ops/ms
[info] Iteration   5: 7726.417 ops/ms
[info] Iteration   6: 7410.291 ops/ms
[info] Iteration   7: 7452.339 ops/ms
[info] Iteration   8: 7825.050 ops/ms
[info] Iteration   9: 7801.677 ops/ms
[info] Iteration  10: 7783.978 ops/ms
[info] Iteration  11: 7788.909 ops/ms
[info] Iteration  12: 7778.982 ops/ms
[info] Iteration  13: 7784.158 ops/ms
[info] Iteration  14: 7771.173 ops/ms
[info] Iteration  15: 7750.280 ops/ms
[info] Iteration  16: 7813.570 ops/ms
[info] Iteration  17: 7845.550 ops/ms
[info] Iteration  18: 7841.003 ops/ms
[info] Iteration  19: 7808.576 ops/ms
[info] Iteration  20: 7847.100 ops/ms
[info] Result "bmks.FindElementBenchmark.findElementPF":
[info]   7715.902 ±(99.9%) 124.303 ops/ms [Average]
[info]   (min, avg, max) = (7410.291, 7715.902, 7847.100), stdev = 143.148
[info]   CI (99.9%): [7591.598, 7840.205] (assumes normal distribution)
[info] # Run complete. Total time: 00:10:01
[info] REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up on
[info] why the numbers are the way they are. Use profilers (see -prof, -lprof), design factorial
[info] experiments, perform baseline and negative tests that provide experimental control, make sure
[info] the benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.
[info] Do not assume the numbers tell you what you want them to tell.
[info] Benchmark                              Mode  Cnt      Score      Error   Units
[info] FindElementBenchmark.findElementDict  thrpt   20  47947.097 ± 1003.440  ops/ms
[info] FindElementBenchmark.findElementPF    thrpt   20   7715.902 ±  124.303  ops/ms
[success] Total time: 603 s, completed Apr 30, 2019 7:33:10 PM