Scala: Under The Hood of Hello World

基于MATLAB的太阳能光伏电力仿真,模拟每日太阳能发电,可视化功率曲线,并通过数值积分计算总能量输出。.zip 1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。 立即下载
The exercise of printing 'Hello World' from a new programming language is so popular because it allows you to see quite a few things about a language straight away, including the style of the syntax, how to print output and the amount of boilerplate required just to start a simple application.

After getting Hello World to work, there's really two directions you could go: you can go forward, and start doing other stuff with the language, or you can go down, drill deeper, by asking the question "How does it work?"

While moving forward is certainly more productive and exciting in the short term, understanding what's going on underneath the covers of your code can be very beneficial and can lead to insights that may affect the way you write code for the rest of your programming life. For instance, if you've done a bit of Java and a bit of Scala, it may have occurred to you that Scala allows you to define objects (as opposed to classes), while Java has no concept of compile-time objects, so how does the Scala compiler map the concept of an object into Java's single-minded view of classes? We'll find out…

Opening the Hood with Scala
Unless you've managed to run a Scala Hello World program accidentally, you have probably read enough of some Scala tutorial, book or blog to know that Scala is compiled to Java Bytecode - the binary language that is read and executed by the Java Virtual Machine (JVM). This means that a good way to get an idea of what actually happens when we run a Scala program is to have a look at the bytecode that is generated when we compile the application.

So, here's your standard Scala Hello World program:
object HelloWorld {
  def main(args: Array[String]) {
    println("Hello World!")
  }
}

If we compile this program and have a look at the output directory for classes, we'll find two Java class files:
-rw-r--r--   1 graham  staff   778 28 Nov 09:43 HelloWorld$.class
-rw-r--r--   1 graham  staff   607 28 Nov 09:43 HelloWorld.class

Two classes? Yep, two classes. We compile one "object" and we end up with two classes. Let's have a look at what's inside these classes.

If you want to see what's going on inside a Java class (or a Scala class or object that's been compiled to a Java class) you can inspect the class file with the JDK tool 'javap'. Depending on the options you provide to javap, it can print you out just a summary of the class' method signatures or you can see a pseudo-English translation of the all compiled bytecodes. Let's start by having a look at just the signatures:
[scala-tests] graham$ javap -classpath . HelloWorld HelloWorld$
Compiled from "HelloWorld.scala"
public final class HelloWorld extends java.lang.Object{
    public static final void main(java.lang.String[]);
    public static final int $tag()       throws java.rmi.RemoteException;
}

Compiled from "HelloWorld.scala"
public final class HelloWorld$ extends java.lang.Object implements scala.ScalaObject{
    public static final HelloWorld$ MODULE$;
    public static {};
    public HelloWorld$();
    public void main(java.lang.String[]);
    public int $tag()       throws java.rmi.RemoteException;
}

Wow! So, we wrote one method - HelloWorld.main() - and we've ended up with 6 methods and one static field across two classes. Obviously not all of this code is relevant to the running of our HelloWorld program, so let's discuss some of the surrounding fluff and then put it out of mind.

What Is This $tag() Thing?
Probably the first obvious thing is that both classes have a method called $tag(). If we have a look at the  Scaladocs for the ScalaObject trait , the base class of all classes and objects compiled by Scala, we'll see no mention of the $tag() method. However, if you have a look at  the source of ScalaObject.scala , you'll see this definition, which is been in the Scaladoc:
  /** This method is needed for optimizing pattern matching expressions
   *  which match on constructors of case classes.
   */ 
  @remote 
  def $tag(): Int = 0 

Basically, the $tag() method is a simple categorisation method akin to java.lang.Object's hashCode() that is used by Scala to make it's much-lauded pattern matching perform better. Interestingly, in  the 2.8.0 branch of Scala , $tag() has been removed, so now that we understand it, we know that we don't really have to worry about understanding it any more!

What Makes It Run?
Having learnt enough to ignore the $tag() method, let's have a look at how our program runs. Your keen eye may have noticed that we have two main() methods - one on the HelloWorld class and one on the HelloWorld$ class. If you're lucky enough to have two keen eyes, you would have noticed that the main() method on HelloWorld is static, but the main() method on HelloWorld$ is not. The significance of this is that, though there are two main() methods, only one of the classes - HelloWorld - can be used to start the application. If I tried to start the application by telling the java command to start with the HelloWorld$ class, the JVM will happily tell me that I'm an idiot:
[scala-tests] graham$ java -cp .:$HOME/Library/Scala/Current/lib/scala-library.jar HelloWorld$
Exception in thread "main" java.lang.NoSuchMethodError: main

Instead of acting like an idiot, let's have a look at what this HelloWorld.main() method does. The javap command allows us to see the actual bytecode instructions that are contained within the class if we pass the -c option:
[scala-tests] graham$ javap -c -classpath . HelloWorld
Compiled from "HelloWorld.scala"
public final class HelloWorld extends java.lang.Object{
public static final void main(java.lang.String[]);
  Code:
   0:    getstatic    #11; //Field HelloWorld$.MODULE$:LHelloWorld$;
   3:    aload_0
   4:    invokevirtual    #13; //Method HelloWorld$.main:([Ljava/lang/String;)V
   7:    return
...

If you've  learnt a little bit about Java bytecode , reading what this method does is pretty simple…
0: This instruction retrieves the value of the static field HelloWorld$.MODULE$ and pushes it onto the stack. We can see both from this line (after the colon) and from the signatures we looked at above that the type of the MODULE$ field is HelloWorld$.
3: This instruction takes the first argument to the method - the String[] that represents the command-line arguments - and pushes it onto the stack.
4: This instruction invokes the main() instance method on the HelloWorld$ object that was pushed onto the stack at 0, passing it the String[] pushed onto the stack at 3.
At the heart of it, this is a pretty simple operation. If we were to write this method ourselves in Java, it would look like this:
public static void main(String[] args) {
    HelloWorld$.MODULE$.main(args);
}

What Is This MODULE$ Thing?
Moving on, I think the next thing we want to find out is, what is MODULE$ and how is it initialised? Chances are you're pretty smart and you've probably figured this out already, so let's just cut straight to the bytes:
[scala-tests] graham$ javap -c -classpath . HelloWorld$
Compiled from "HelloWorld.scala"
public final class HelloWorld$ extends java.lang.Object implements scala.ScalaObject{
public static final HelloWorld$ MODULE$;

public static {};
  Code:
   0:    new    #10; //class HelloWorld$
   3:    invokespecial    #13; //Method "":()V
   6:    return

public HelloWorld$();
  Code:
   0:    aload_0
   1:    invokespecial    #17; //Method java/lang/Object."":()V
   4:    aload_0
   5:    putstatic    #19; //Field MODULE$:LHelloWorld$;
   8:    return
...

Again, reading this is pretty simple. Basically it's creating a singleton instance of HelloWorld$ which is stored in a public static field. There's a static block that creates a new HelloWorld$ object and there's a HelloWorld$() constructor, which does something which I find a little bit odd. If we translated it into Java, we'd have something like this:
public final class HelloWorld$ {
    public static final HelloWorld$ MODULE$;

    static {
        new HelloWorld$();
    }

    public HelloWorld$() {
        super();
        MODULE$ = this;
    }
}

Does that assignment in the constructor look a little weird to you? The constructor is setting the value of the static MODULE$ field. This is especially strange seeing as MODULE$ is a final static field. If you tried to use this Java code you'd find that it wouldn't even compile. At first I thought that this was so odd that I must have interpreted the bytecode incorrectly, so I wrote this little Java class to test out what happens when you call the HelloWorld$() constructor directly:
public class HelloWorldTest {
    public static void main(String[] args) {
        System.out.println(System.identityHashCode(HelloWorld$.MODULE$));
        new HelloWorld$();
        System.out.println(System.identityHashCode(HelloWorld$.MODULE$));
    }
}

Sure enough, the output of running this code shows that every invocation of the HelloWorld$() constructor does indeed change the value of MODULE$, even though it's final:
2114843907
1179703452

That's a bit of an oddity, but there's a lesson there - never call the constructor of a Scala object from Java code - there is no telling what kind of havoc you may wreak if you instantiate a second instance of an object that is assumed to be a singleton within your Scala code.

Dude, Where's My Code?
Okay, so nothing we've examined up until now has had ANYTHING to do with the one line of imperative code that we wrote in Scala. But we're almost there, as there's only one piece of the double-main() puzzle left to examine - HelloWorld$.main():
[scala-tests] graham$ javap -c -classpath . HelloWorld$
Compiled from "HelloWorld.scala"
public final class HelloWorld$ extends java.lang.Object implements scala.ScalaObject{
...
public void main(java.lang.String[]);
  Code:
   0:    getstatic    #26; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   3:    ldc    #28; //String Hello World!
   5:    invokevirtual    #32; //Method scala/Predef$.println:(Ljava/lang/Object;)V
   8:    return

And here we finally see the code that we actually wanted to run. This method is extremely similar to the main() method we saw in HelloWorld: It pushes the singleton instance of Scala's Predef object  onto the stack, pushes the "Hello World!" constant onto the stack and then invokes the Predef.println() method.

Can You Repeat That In English?
Let's summarise what we found in the bytecode of this HelloWorld program. When you define a main() method on a Scala object, the Scala compiler splits the responsibility of running your application into two classes. One class has the same name as your object and contains a static method that is invoked by the JVM to start the application. The other class, which has the same name as your object except with a dollar sign ($) at the end, contains the actual code of your object's main() method in an instance method called main(), as well as a constructor and a public static field for creating and accessing a singleton instance of this special class.

If you want to read some more about why the code from you object ends up in a class that has a dollar sign at the end of its name, you might like to do some reading on  companion objects in Scala .

Bonus Marks for Pointing Out Something Nerdy
There is one other little surprise in here that I skipped over and which I only noticed while looking at  a decompilation of a Java HelloWorld program . The HelloWorld class generated by the Scala compiler has no constructor at all. Not one. It is im-possi-ble to create an object of type HelloWorld. This is a minor departure from the convention of Java where every class has at least one constructor, by virtue of the Java compiler generating one for you if you decide not to define one. This little difference has absolutely no effect on anything at all, but I always find it interesting when the Scala guys decide to contradict ideas that have been Java "laws" since what seems like the beginning of time. It almost feels like they're slaying  Jack Harkness .
人脸识别签到考勤系统实战源码 这是一套可直接运行的人脸识别智能签到考勤系统,基于OpenCV YuNet人脸检测与SFace特征识别实现,全程本机运行,数据保存在本地SQLite,不上传任何服务器。配套交付完整Python源码、9章实战教程(md/html/pdf三种格式)、逐步骤操作截图和答辩PPT讲解。 系统围绕五个功能模块展开:人脸注册支持照片批量导入并提取特征入库;识别签到支持照片或摄像头两种方式,实时框出人脸并标注姓名、相似度与考勤状态;考勤规则引擎按config.py里配置的上下班时间与宽限分钟,自动判定迟到、早退、缺勤;Tkinter管理面板完成人员管理、流水查询与月度汇总;最后通过openpyxl一键导出整月考勤矩阵,正常绿、迟到黄、缺勤红,Excel打开即用。 选型上特意选了YuNet+SFace路线:纯pip安装免编译,CPU单帧识别不到100ms,两个ONNX模型共约37MB,出自OpenCV官方模型仓库,毕设报告引用有据可查。教程第7章整理了16条Windows下真实踩过的报错及排查方法,第8章给出换模型、换人脸、加功能的二次开发路径。 适合做计算机视觉方向毕设或课程设计的学生,也适合想给班级、实验室、小团队搭一套本地签到工具的Python学习者。运行环境为Python 3.9以上、Windows 10/11,不需要GPU。 使用时先pip install -r requirements.txt装齐依赖,再运行download_data.py下载模型,最后启动main.py即可进入图形界面;命令行register、recognize、report子命令也可脱离界面单独调用。 立即下载

相关推荐

【电力负荷预测】项目介绍 MATLAB实现基于BO-Transformer-LSTM贝叶斯优化算法(BO)优化Transformer-LSTM组合模型进行居民用户多步电力负荷预测(含模型描述及部分示例

内容概要:本文介绍了一个基于BO-Transformer-LSTM的组合模型,用于实现居民用户多步电力负荷预测的完整项目实例。该模型融合Transformer的全局注意力机制与LSTM的局部时序记忆能力,构建能够捕捉长时依赖与周期性特征的深度学习架构,并引入贝叶斯优化(BO)自动搜索最优超参数组合,提升预测精度与训练效率。项目涵盖从原始数据清洗、特征工程、滑动窗口样本构建、模型设计到超参数优化、反归一化及多步误差评估的全流程,强调时间顺序划分以防止信息泄露,并通过周期编码、外生变量融合等方式增强数据表达能力。文中提供了详细的MATLAB代码示例,包括数据预处理、网络搭建、贝叶斯优化配置和预测结果评估等关键步骤。 适合人群:具备一定机器学习和时间序列分析基础,熟悉MATLAB编程环境,从事电力系统预测、智能电网、负荷管理等相关领域的研究人员、工程师及研究生。 使用场景及目标:①应用于居民级或多用户聚合负荷的短期至中期多步预测(如未来24小时);②服务于配电系统运行调度、需求响应基线设定、家庭能源管理系统优化、分布式能源协调控制等实际工程场景;③为科研提供可复现的深度学习+贝叶斯优化的技术路线参考。 阅读建议:此资源以实际项目为导向,建议读者结合提供的代码逐步实现并调试模型,重点关注数据质量控制、时间特征编码、组合网络结构设计与贝叶斯优化稳定性之间的协同关系,在实践中深入理解多步预测中的误差累积机制与超参数敏感性问题。

深入理解Scala默认参数函数:从方法重载到优雅API设计

我写这篇文章的时候,特意没罗列默认参数有多少种用法——因为用法很简单,谁都能写。默认参数为什么重要?可选参数。Java里你想要可选参数?写重载方法。想要几个?写一堆。代码臃肿,维护痛苦。Scala的默认参数把这件事简化了——一行函数签名,编译器帮你生成所有的重载方法。调用方想用默认值就用默认值,想改哪个就改哪个,不用管顺序。把重复的事情交给编译器,让程序员专注在业务逻辑上。你不用手写重载方法——编译器帮你写。你不用记参数顺序——命名参数帮你记。你不用写Builder类——默认参数就是Builder。

https://starzy1990.github.io/ 756

国央企创新负责人如何通过平台实现科研成果的快速识别与转化?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

深入理解Scala嵌套函数:作用域封装之道

我写这篇文章的时候,特意没罗列嵌套函数有多少种写法——因为写法很简单,谁都能写。嵌套函数为什么重要?辅助逻辑的作用域应该是多大?Java里你写辅助逻辑,只能写到类级别——因为Java的方法必须定义在类级别。但很多辅助逻辑其实只属于某一个函数,不属于整个类。你把它们写到类级别,就造成了作用域放大——本来应该是函数内部的东西,变成了类级别的东西。Scala的嵌套函数把这个问题解决了——辅助逻辑可以精确地封装在主函数内部。它直接访问外层函数的变量,不用把上下文传来传去。它不暴露到类级别,不造成API膨胀。

https://starzy1990.github.io/ 757

PotPlayer自用皮肤

自用 PotPlayer 皮肤,仅微调了字体大小与颜色,是按个人习惯调整,未做适配性调整。

2-shell及常用命令-续.pdf

2-shell及常用命令-续.pdf

深入理解Scala可变参数函数:从Java数组语法到优雅集合传递

我写这篇文章的时候,特意没罗列可变参数有多少种用法——因为用法很简单,谁都能写。Scala的可变参数为什么比Java好用?不是因为它有:_*这个语法——而是因为它的底层是Seq,不是数组。Java的可变参数是数组的语法糖——你传List进去,它不认,因为List不是数组。你想传?自己转。Scala的可变参数是Seq的语法糖——你传任何序列进去,只要用:_*展开就行。不用转,不用强转,一行代码搞定。**这就是函数式语言的设计哲学:可变参数不是"数组的便捷写法",它是"序列的便捷写法"。

https://starzy1990.github.io/ 440

MySQL等保三级合规实践:如何安全配置root账户的本地与受信主机登录策略

本文详细介绍了MySQL在等保三级合规框架下如何安全配置root账户的本地与受信主机登录策略。通过分析root账户的特殊保护需求,提供三种安全加固方案,包括限制访问范围、限定登录IP和完全禁止远程登录,并指导创建安全的远程管理账户。文章还涵盖了密码策略强化、日志审计配置和网络层防护等关键合规要求,帮助用户实现MySQL的等保三级全面合规。

weixin_42522964的博客 259

深入理解Scala Map:从实现原理到工程实践

我写这篇文章的时候,特意没罗列Map有多少个方法——因为那些东西官方文档都有,查一下就行。Map到底解决了什么问题?它不是"带key的列表",它是一个"从key到value的映射函数"。它用哈希表的O(1)查找,换来了通过key快速找到value的能力。在大数据开发里,Map无处不在——维度关联、配置映射、计数统计、分组聚合、缓存索引。理解了Map,你就理解了大数据处理里最核心的几个操作:查找、映射、聚合。很多人用了几年Map,还停留在"new一个HashMap,然后put put put"的阶段。

https://starzy1990.github.io/ 391

Electron多窗口开发避坑指南:Pinia状态同步的3种解决方案对比

本文深入探讨了在Electron多窗口应用中实现Pinia状态同步的三种核心方案。针对Electron多窗口架构下状态隔离的挑战,文章对比了基础事件通信、共享存储以及智能Pinia插件等方案的优劣与适用场景,并提供了生产级的实现指南与选型建议,帮助开发者构建健壮高效的桌面应用。

spice的博客 479

01_MySQL下载、安装与配置(以MySQL8.0.31版本为例)

1.点击下载好的mysql安装包 进入到mysql installer界面。2.选择MySQL Servers选项 一直下拉。

4819

深入理解Scala匿名函数:函数式编程基石

我写这篇文章的时候,特意没罗列匿名函数有多少种写法——因为写法很简单,谁都能写。匿名函数为什么是函数式编程的基石?把函数当参数传。你不能把函数当参数传,就没有map、filter、reduce这些集合操作。没有这些集合操作,就没有声明式编程。没有声明式编程,就没有函数式编程。Java花了很长时间才意识到这一点——Java 8才加了Lambda。但Java的Lambda是不完整的——它只能捕获final变量,不能修改变量。它是一个"阉割版"的闭包。Scala呢?

https://starzy1990.github.io/ 519

自动驾驶——最优控制算法(LQR)工程化总结

到近段时间,真正在我们的控制器上运行最优控制算法(LQR),一步一个脚印,从开始只是知道其“控制理论”的阶段、再到对着一堆网上的资料和公式一筹莫展不知何着手、再到初步实现了LQR算法的开发(但是使用的扭矩环控制,控制的不好,而且由于各种原因被delay,迟迟无法落地),直到大上个星期,泊车平台有此LQR开发需求,又重新了开始了算法的研发,用时一个周时间完成了算法开发,然后再用一个周时间进行实车最优控制算法验证与调试,取得了很大的进展,由于执行器是转角控制的,这无疑少了很多的工作量。

qq_40464599的博客 2787

深入理解Scala偏应用函数:函数工厂设计

我写这篇文章的时候,特意没罗列偏应用函数有多少种写法——因为写法很简单,谁都能写。偏应用函数为什么重要?不是因为"它可以固定一部分参数"——而是因为它让你可以把函数当工厂用。Java里你想写一个"专用函数",怎么办?——写一个新方法,重载,或者用Builder。Scala呢?——一行占位,就把通用函数变成了专用函数。函数是一等公民,你可以加工它——固定参数、组合参数、变换参数——得到新的函数。Java的方法是死的——你定义的时候几个参数,调用的时候就得传几个。

https://starzy1990.github.io/ 399

游戏服务器框架之跨服(一)

如今的游戏开发,不搞个跨服玩法都不好意思说在做游戏了(当然,也跟游戏类型有关,一些轻度休闲游戏可以排除在外)。跨服玩法的设计,可以进一步激发玩家追求高战力的虚荣心,也可以汇聚玩家数量,避免单服日活跃低呈现死服现象。 几种常见的跨服玩法拓扑结构 一,不同游戏服的玩家进入中立服务器进行战斗,例如跨服天梯类玩法。 游戏服有很多个节点,中心服务器也有很多节点。只要保证对战的双方同时进入同一个中心服游戏进程即可。 二,若干个游戏服组成一个社区,全部服务器包含多个社区,例如世界服玩法。 三,游戏服A玩

littleschemer的博客 5773

华为OD机试真题 Java&Go 实现【优雅子数组】【100%通过率】【2022.11 Q4 新题】

如果一个数组中出现次数最多的元素出现大于等于K次,被称为K -优雅数组,k也可以被称为优雅阈值。例如,数组1,2,3,1、2,3,1,它是一个3-优雅数组,因为元素1出现次数大于等于3次,数组1,2,3,1,2就不是一个3-优雅数组,因为其中出现次数最多的元素是1和2,只出现了2次。给定一个数组A和k,请求出A有多少子数组是k-优雅子数组。

MISAYAONE的博客 1万+

【Spark】 04键值对 RDD:创建、常用操作与数据分区

介绍 Spark 键值对 RDD 的创建方式、聚合、分组、连接、排序与行动操作,并结合 PageRank 示例讲解数据分区、分区器复用与自定义分区方式。

qq_46126258的博客 376

嵌入式SDIO 总线面试题及参考答案

SDIO 的 4 位总线模式是一种提高数据传输效率的工作模式。在传统的 1 位总线模式下,数据只能通过一根数据线(DAT0)进行传输,这限制了数据传输的带宽和速度。而在 4 位总线模式下,DAT0 - DAT3 这 4 根数据线同时用于数据传输,相当于在同一时间内可以传输 4 倍于 1 位模式的数据量,从而显著提高了数据传输的带宽和速度。要通过 CMD6 命令将 SDIO 总线从当前模式切换到 4 位总线模式,需要遵循以下步骤:第一步,主设备需要确保 SDIO 卡支持 4 位总线模式。

大模型大数据攻城狮的专栏 1719

大数据Spark(八十二):Spark 算子综合案例

本文通过四个典型Spark算子应用案例,系统讲解了单词频次过滤、PV/UV统计、二次排序及分组取TopN的实现方法。涵盖flatMap、mapToPair、reduceByKey、distinct、sortByKey、groupByKey等核心算子的组合使用,提供Java与Scala双语言实现,兼顾可读性与实用性。强调根据数据规模选择合适方案,避免内存溢出,适用于大数据处理场景的实战参考。

Lansonli(蓝深李)的博客 620

混响效果的编程实现:Schroeder混响模型与Moorer型混响

Schroeder混响模型是由Manfred R. Schroeder在1962年提出的,它基于一系列串联的反射器(Allpass Comb Filters)和并联的反射器(Feedback Comb Filters)构成。Schroeder混响模型是由Manfred R. Schroeder在1962年提出的,它基于一系列串联的反射器(Allpass Comb Filters)和并联的反射器(Feedback Comb Filters)构成。通过调整各个反射器和全通滤波器的参数,可以实现不同的混响效果。

2301_79326857的博客 1082

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

深入理解Scala递归函数:从栈溢出到尾调用优化

我写这篇文章的时候,特意没罗列递归有多少种写法——因为递归的语法很简单,谁都能写。为什么Java的递归会栈溢出,而Scala的不会?不是因为Scala更厉害——而是因为Scala是函数式语言,递归是它的核心特性之一。它从设计之初就考虑了尾调用优化的问题。Java是命令式语言,它的核心是对象和方法,递归只是一个"能用但不推荐"的特性。Java程序员写递归:栈溢出,不敢用Scala程序员写递归:尾递归,随便写递归不是洪水猛兽,栈溢出是因为你没写对。你可以用递归的优雅写法,获得循环的性能。

https://starzy1990.github.io/ 626

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

深入理解Scala可变Map:动态构建场景下的性能与设计权衡

我写这篇文章的时候,特意没罗列可变Map有多少个方法——因为那些东西官方文档都有,查一下就行。为什么需要可变Map?不是因为"它就是Java HashMap的Scala版",而是因为在动态构建数据的场景下,不可变Map的性能不够好。你要在循环里不断往Map里加key-value对,用不可变Map就是O(n²)的灾难,用可变Map就是O(n)的高效。但可变Map也不是万能的。它只适合"构建"场景——你在一个方法内部,动态构建一个Map,最后输出一个不可变Map。

https://starzy1990.github.io/ 361

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

深入理解Scala高阶函数:函数式编程核心

我写这篇文章的时候,特意没罗列高阶函数有多少种用法——因为用法很简单,谁都能写。高阶函数为什么是函数式编程的核心?把函数当一等公民,用函数来抽象和组合逻辑。没有高阶函数,函数就不能当参数传——那你就没有map、filter、reduce。没有这些,你就只能写for循环——命令式编程。有了高阶函数,你可以把逻辑封装成函数,传给其他函数——你可以组合函数、变换函数、生成函数。这就是函数式编程。Java花了很长时间才意识到这一点——Java 8加了Lambda和Stream。

https://starzy1990.github.io/ 516

深入理解Scala元组:从多返回值到模式匹配的桥梁

函数式编程里,函数的参数和元组是一一对应的。在函数式编程里,一个函数可以看成是接收一个参数、返回R的函数。这个叫"函数的元组化"(tupled)。而Scala的类型系统在处理多参数函数的时候,需要为每个参数数量生成对应的函数类型——、…、。因为函数最多到Function22,所以元组也最多到Tuple22。这是一个统一的设计——元组和函数,共享同一个N的上限。那22以上怎么办?用嵌套元组或者case class。// 超过22个元素:用嵌套。

https://starzy1990.github.io/ 701

深入理解Scala函数定义:从方法到函数的类型跨越

最常用的方式。定义一个方法,属于当前类/对象。name特点:有名字、有参数类型、有返回类型(可以省略,编译器推断)、函数体用连接。定义一个函数值,它是一个对象,可以到处传。name特点:用val定义(因为它是值),参数和返回类型写在括号里,=>后面是函数体。我写这篇文章的时候,特意没罗列函数有多少种写法——因为那些语法东西,查文档就有。Scala为什么要有函数这个概念?不是因为"函数式编程嘛,函数是一等公民"——这句话说了等于没说。当你需要对一组数据做变换的时候,你需要一个"可以传进去的操作"。

https://starzy1990.github.io/ 711

大数据Spark(八十三):Spark中的分区器Partitioner介绍

本文介绍Spark中Partitioner的作用及三种实现方式:HashPartitioner(基于哈希取模,默认分区器,高效但易倾斜)、RangePartitioner(按键范围分区,支持排序,数据均衡性好)和自定义分区器(按业务规则分配,灵活应对特殊需求)。合理选择分区器可优化shuffle性能,提升作业效率。

Lansonli(蓝深李)的博客 576
上一篇: Classes and Fields in Scala
下一篇: Know Your Stack - Scala to Java to Bytecode to Assembly
DViewer
博客等级 码龄16年 16粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值