转载:理解scala中的Symbol
相信很多人和我一样,在刚接触Scala时,会觉得Symbol类型很奇怪,既然Scala中字符串都是不可变的,那么Symbol类型到底有什么作用呢?
简单来说,相比较于String类型,Symbol类型有两个比较明显的特点:节省内存和快速比较。在进入正题之前,让我们先来了解一下Java中String的intern()方法。
一、String的intern方法介绍
Oracle的开发文档上讲解的很详细:String类内部维护一个字符串池(strings pool),当调用String的intern()方法时,如果字符串池中已经存在该字符串,则直接返回池中字符串引用,如果不存在,则将该字符串添加到池中,并返回该字符串对象的引用。执行过intern()方法的字符串,我们就说这个字符串被拘禁了(interned)。默认情况下,代码中的字符串字面量和字符串常量值都是被拘禁的,例如:
String s1 = "abc";
String s2 =new String("abc"); //返回true
System.out.println(s1 == s2.intern());
同值字符串的intern()方法返回的引用都相同,例如:
String s2 = new String("abc");
String s3 = new String("abc"); //返回true
System.out.println(s2.intern() == s3.intern());
//返回false
System.out.println(s2 == s3);
二、Symbol类型的主要特点
下面接着介绍Symbol类型的两个特点。
1. 节省内存
在Scala中,Symbol类型的对象是被拘禁的(interned),任意的同名symbols都指向同一个Symbol对象,避免了因冗余而造成的内存开销。而对于String类型,只有编译时确定的字符串是被拘禁的(interned)。Scala测试代码如下:
val s = 'aSymbol
//输出true
println( s == 'aSymbol)
//输出true
println( s == Symbol("aSymbol"))
2. 快速比较
由于Symbol类型的对象是被拘禁的(interned),任意的同名symbols都指向同一个Symbol对象,而不同名的symbols一定指向不同的Symbol对象,所以symbols对象之间可以使用操作符==快速地进行相等性比较,常数时间内便可以完成,而字符串的equals方法需要逐个字符比较两个字符串,执行时间取决于两个字符串的长度,速度很慢。(实际上,String.equals方法会先比较引用是否相同,但是在运行时产生的字符串对象,引用一般是不同的)
三、Symbol类型的应用
Symbol类型一般用于快速比较,例如用于Map类型:Map<Symbol, Data>,根据一个Symbol对象,可以快速查询相应的Data, 而Map<String, Data>的查询效率则低很多。
四、小结
利用String的intern方法也可以实现Map<String, Data>的键值快速比较,但是由于需要显式地调用intern()方法,在编码时会造成很多的麻烦,而且如果忘了调用intern()方法,还会造成难以寻找的bug。从这个角度看,Scala的Symbol类型不仅有效率上的提升,而且也简化了编码的复杂度。
转载:理解scala中的Symbol的更多相关文章
- 理解Scala中的Extractor
引言 最近抱着<Programming in Scala>(英文第二版)在死啃Scala.在阅读第26章Extractor时,偶然在Stack Overflow上搜到一个帖子<Sca ...
- (转载)理解Java中的引用传递和值传递
关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天 ...
- 【Todo】【转载】Scala中Array, List, Tuple的区别
参考了这篇文章: https://my.oschina.net/u/1034176/blog/512314 1. 在Scala 2.7中,Array.List都不能混合类型,只有Tuple可以:而在S ...
- 转载:scala中的implicit
掌握implicit的用法是阅读Spark源码的基础,也是学习Scala其它的开源框架的关键,implicit 可分为: 隐式参数 隐式转换类型 隐式调用函数 1.隐式参数 当我们在定义方法时,可以把 ...
- 理解ES6中的Symbol
一.为什么ES6引入Symbol 有时候我们在项目开发的过程中可能会遇到这样的问题,我写了一个对象,而另外的同时则在这个对象里面添加了一个属性或是方法,倘若添加的这个属性或是方法是原本的对象中本来就有 ...
- 转载:scala中:: , +:, :+, :::, ++的区别
原文链接:https://segmentfault.com/a/1190000005083578 初学Scala的人都会被Seq的各种操作符所confuse.下面简单列举一下各个Seq操作符的区别. ...
- 转载:scala中的:+\+:\::\:::
原文链接:https://segmentfault.com/a/1190000005083578 初学Scala的人都会被Seq的各种操作符所confuse.下面简单列举一下各个Seq操作符的区别. ...
- Scala中的协变,逆变,上界,下界等
Scala中的协变,逆变,上界,下界等 目录 [−] Java中的协变和逆变 Scala的协变 Scala的逆变 下界lower bounds 上界upper bounds 综合协变,逆变,上界,下界 ...
- 转载 深入理解JavaScript中的this关键字
转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字 1. 一 ...
随机推荐
- C# vb .net实现圆角矩形特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的圆角矩形效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- git安装用法和常用命令
目录 git 下载 安装 git 工作中常用命令 Git常用命令汇总以及其它相关操作 或者 常出错误: 常用修改: 题外话(相关概念) git 下载 安装 1.下载Git,官网地址:https://g ...
- VUE回顾基础3
1.方法 在vue模板里函数被定义为方法来使用,将函数放在methods对象里,作为一个属性,就可以在模板里使用它 this:在方法中this指向该方法所属的组件,可以使用this方文档data对象的 ...
- Linux E667 同步失败
在使用Vim编辑/proc目录下的文件后,保存,显示"E667 同步失败" 原因 因为proc这个目录是一个虚拟文件系统,它放置的数据都是在内存中,本身不占有磁盘空间,所以使用Vi ...
- Git管理修正(取消跟踪、合并commit)
本文总结了最近使用Git时候遇到的两个问题: 1. 当将不必要跟踪的文件加入到仓库后如何处理? 2. 提交了多个功能相同的commit后如何处理? 总结经验 在创建仓库的一开始,就要设置号.gitig ...
- day 14作业
作业 现有文件info.txt, 其内容如下: alpha male 18 1000 bravo male 28 2000 charlie female 38 3000 delta female 48 ...
- Centos7搭建Harbor私有仓库(二)
1 说明 前文Centos7搭建Harbor私有仓库(一)中成功搭建了Harbor,但,是以http方式搭建的,这里我们修改为https方式 以下基于镜像CentOS-7-x86_64-Minimal ...
- 【Docker】docker的安装和常用命令
一.docker安装和启动 1.yum 命令 yum install docker 2.docker启动命令 sudo systemctl start docker 二.docker常用命令 dock ...
- moviepy的常见用法
看了,还是自己弄这些方便. #字幕 >>> from moviepy.video.tools.subtitles import SubtitlesClip >>> ...
- Go - IDE的选择与GoLand的安装
目录 常用编辑器的选择 IDE的选择 GoLand的下载与安装 下载 安装 常用编辑器的选择 编写go程序,可以选择的编辑软件有很多,其中包括: notepad++ sublime visual st ...