转载:理解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. 一 ...
随机推荐
- Spring Data Solr入门小Demo
package com.offcn.pojo; import java.io.Serializable; import java.math.BigDecimal; import java.util.D ...
- Java自学-控制流程 break
Java的break语句 结束循环 示例 1 : break; 直接结束当前for循环 public class HelloWorld { public static void main(String ...
- Java自学-控制流程 continue
Java的 continue语句 继续下一次循环 示例 1 : continue 如果是双数,后面的代码不执行,直接进行下一次循环 public class HelloWorld { public s ...
- 用 node.js 模仿 Apache 的部分功能
首先,这个例子用到了服务端渲染的技术.服务端渲染,说白了就是在服务端使用模板引擎,这里我先简单的介绍一下服务端渲染与客户端渲染之间的区别. 服务端渲染与客户端渲染之间的区别: 客户端渲染不利于搜索引擎 ...
- 纽约LangeEylandt长岛LongIsland
LangeEylandt n.长岛(美国) 纽约长岛 纽约长岛 (LongIsland)是北美洲在大西洋内的一个岛,最早追溯到十七世纪的1650年被命名为Lange Eylandt [1] ,位于北美 ...
- form组件 初始化
class MyForm(Form): user = fields.ChoiceField( # choices=((1, '上海'), (2, '北京'),), initial=2, widget= ...
- dedeCMS 两个站共用同一个数据库 图片路径统一
1 . 在 /include/extend.fun.php 中增加方法: function replaceurl($newurl){ $newurl=str_replace('src="/ ...
- php框架路由美化后提示No input file specified
此问题出现在.htaccess上 Apache按如下代码修改即可: RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond % ...
- Linux一些服务的启动命令
http:服务service httpd start 启动 service httpd restart 重新启动 service httpd stop 停止服务 启动ssh服务 # /etc/init ...
- rhce 考试题目总结
rhce 考试题目总结归类 开机需要做的事: 检查系统版本 配置yum源 修改selinux的模式 ping一下server机器 1.分区类题目 1.1 rhcsa 第十五题 添加swap分区 要点: ...