【Java】Map杂谈,hashcode()、equals()、HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap
参考的优秀文章:
《Java编程思想》第四版
《Effective Java》第二版
Map接口是映射表的结构,维护键对象与值对象的对应关系,称键值对。
> hashcode()和equals()
hashcode()和equals()即用于识别对象的身份。
在HashMap或类似的实现中,查找一个对象,是通过hashcode()返回的散列值映射到一个范围内的下标,在通过equals()比较此下标连接的链表是否存在相同的对象。
简单来说,hashcode()用于参考、快速定位(缩减范围),真正是否等于是依赖equals()。
默认的hashcode()和equals()
如何对象没有覆盖这两个方法,那么就是继承Object对象的。
在Object中,hashcode()是使用对象的地址计算散列值;equals()只比较对象的地址。
必要的时候,我们需要覆盖这两个方法。
覆盖这两个方法有什么原则呢?
equals()的覆盖,主要是基于此对象的业务。
而hashcode()的覆盖原则,详情可参见《Effective Java》的“覆盖equals时总要覆盖hashcode”一节。
有几个比较重要的原则:
1、两个equals相等的对象,其hashcode是相等的。
2、两个equals不等的对象,其hashcode有可能是相等的。
3、好的hashcode()应产生分布均匀的散列码。
基于第3点,《Effective Java》有具体的建议。
1、定义变量result为非零的数。
2、用公式result = 31 * result + c,其中c是类中各个域的散列值。
用Eclipse生成的hashcode()与此原则类似,我们可以看看:
public class User {
private Integer id;
private String name;
private boolean flag = false;
private long phoneNumber;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (flag ? 1231 : 1237);
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + (int) (phoneNumber ^ (phoneNumber >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (flag != other.flag)
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (phoneNumber != other.phoneNumber)
return false;
return true;
}
}
> 常用的Map实现
Map接口有几个常用的实现类,HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap。其中HashMap最常用。
HashMap,基于散列表实现,查找速度快(依赖hashcode()和equals()),存放元素无序。
TreeMap,基于红黑树实现,存放有序(依赖Compareable)。
LinkedHashMap,基于散列表、双向链表实现。如HashMap的查找速度,遍历时有序(默认为插入顺序,可通过构造方法设置“最近最少使用(Least Recently Used)顺序”)。
ConcurrentHashMap,线程安全的HashMap,用于替代HashTable(线程安全,但基于整个对象的锁实现的,效率不高),而ConcurrentHashMap是采用分段加锁的方式实现,提升了效率。
代码演示LinkedHashMap的两种排序:
import java.util.LinkedHashMap;
import java.util.Map; public class LinkedHashMapTester { public static void main(String[] args) { System.out.println("LinkedHashMap 根据插入顺序排列:");
Map<String, String> map = new LinkedHashMap<String, String>();
for (Integer i = 0; i < 5; i++) {
map.put("k" + i.toString(), "v" + i.toString());
} for (Integer i = 10; i > 5; i--) {
map.put("k" + i.toString(), "v" + i.toString());
} System.out.println(map);
map.get("k10");
System.out.println(map); System.out.println("LinkedHashMap 根据最近最少使用(Least Recently Used)顺序排列:");
map = new LinkedHashMap<String, String>(16, 0.75f, true); // 没有了其他构造方法设置其排序为true了。初始容量、加载因子使用默认的16和0.75。
for (Integer i = 0; i < 5; i++) {
map.put("k" + i.toString(), "v" + i.toString());
} for (Integer i = 10; i > 5; i--) {
map.put("k" + i.toString(), "v" + i.toString());
} System.out.println(map);
map.get("k10");
System.out.println(map);
} }
日志,注意看使用“K10”后“K10”的位置:
LinkedHashMap 根据插入顺序排列:
{k0=v0, k1=v1, k2=v2, k3=v3, k4=v4, k10=v10, k9=v9, k8=v8, k7=v7, k6=v6}
{k0=v0, k1=v1, k2=v2, k3=v3, k4=v4, k10=v10, k9=v9, k8=v8, k7=v7, k6=v6}
LinkedHashMap 根据最近最少使用(Least Recently Used)顺序排列:
{k0=v0, k1=v1, k2=v2, k3=v3, k4=v4, k10=v10, k9=v9, k8=v8, k7=v7, k6=v6}
{k0=v0, k1=v1, k2=v2, k3=v3, k4=v4, k9=v9, k8=v8, k7=v7, k6=v6, k10=v10}
【Java】Map杂谈,hashcode()、equals()、HashMap、TreeMap、LinkedHashMap、ConcurrentHashMap的更多相关文章
- java:Map借口及其子类HashMap四
java:Map借口及其子类HashMap四 使用非系统对象作为key,使用匿名对象获取数据 在Map中可以使用匿名对象找到一个key对应的value. person: public class Ha ...
- java:Map借口及其子类HashMap五,identityHashMap子类
java:Map借口及其子类HashMap五,identityHashMap子类 了解:identityHashMap子类 一般情况下,标准的Map,是不会有重复的key值得value的,相同的key ...
- java:Map借口及其子类HashMap二
java:Map借口及其子类HashMap二 重点:所有的集合必须依赖Iterator输出 Map<String, Integer> map = new HashMap<String ...
- 【Java入门提高篇】Day28 Java容器类详解(十)LinkedHashMap详解
今天来介绍一下容器类中的另一个哈希表———>LinkedHashMap.这是HashMap的关门弟子,直接继承了HashMap的衣钵,所以拥有HashMap的全部特性,并青出于蓝而胜于蓝,有着一 ...
- Java集合详解6:TreeMap和红黑树
Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储 ...
- Java 数据类型:集合接口Map:HashTable;HashMap;IdentityHashMap;LinkedHashMap;Properties类读取配置文件;SortedMap接口和TreeMap实现类:【线程安全的ConcurrentHashMap】
Map集合java.util.Map Map用于保存具有映射关系的数据,因此Map集合里保存着两个值,一个是用于保存Map里的key,另外一组值用于保存Map里的value.key和value都可以是 ...
- 接口java.util.Map的四个实现类HashMap Hashtable LinkedHashMap TreeMap
java中HashMap,LinkedHashMap,TreeMap,HashTable的区别 :java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMa ...
- Map,Hashmap,LinkedHashMap,Hashtable,TreeMap
java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap. Map主要用于存储健值对, ...
- JAVA基础学习-集合三-Map、HashMap,TreeMap与常用API
森林森 一份耕耘,一份收获 博客园 首页 新随笔 联系 管理 订阅 随笔- 397 文章- 0 评论- 78 JAVA基础学习day16--集合三-Map.HashMap,TreeMap与常用A ...
随机推荐
- ef 5 在 DropCreateDatabaseAlways 报错,the connection is currently used
go sp_who2 -- db_id 数据库名称,查询出来的结果执行一遍就能关闭所有连接 SELECT N'kill '+ CAST(spid AS varchar) FROM master..sy ...
- 不同版本mysql语句不兼容原因
一般是sql_mode不相同,可以认为规则不一致.(语法的变化非常小,一般可以忽略) 如果想要导入不同版本的数据.可以: 手动处理一些导入错误或者采用其他的办法. 或者 修改sql_mode.具体修改 ...
- scan & ATPG
Testability用来表征一个manufactured design的quality. 将testability放在ASIC前端来做,成为DFT(Design For Test),用可控(cont ...
- [Ubuntu] Ubuntu DNS服务器配置
服务器IP:10.68.19.61 操作系统:Ubuntu 13.04 DNS程序:Bind9 测试域名:mycloud.com 目标IP:10.68.19.134 配置步骤 1.安装BIND9程序包 ...
- php防sql注入
[一.在服务器端配置] 安全,PHP代码编写是一方面,PHP的配置更是非常关键. 我 们php手手工安装的,php的默认配置文件在 /usr/local/apache2/conf/php.ini,我们 ...
- Ubuntu1404: 将VIM打造为一个实用的PythonIDE
参考: http://www.tuicool.com/articles/ZRv6Rv 说明: 内容非原创, 主要是做了整合和梳理. 在 ubuntu14.04 & debian 8 下测试通 ...
- 160927、用jquery 重置表单的方法
清空 我们项目小小部分的搜索条件: 客户要做的是,只要一键 "清空搜索条件" 即可清空维护地点.订单ID等条件. js函数 //重置表单 function resetform(){ ...
- LUA之面向对象
Account = { balance=0, withdraw = function (self, v) self.balance = self.balance - v end } function ...
- laravel数据库的创建和迁移
数据库建立及迁移 Laravel 5 把数据库配置的地方改到了 `learnlaravel5/.env`,打开这个文件,编辑下面四项,修改为正确的信息: ? 1 2 3 4 5 6 7 DB_HOST ...
- windows prompt personalize 设置cmd提示的相关
由于有一篇随笔种我说要引用这篇文章,所以不得已也出来了,就像你说大话『我明天去吃屎』,结果你做到了. 我这记录一下有关windows prompt这是的变量,我不知道这算不算变量,因为windows变 ...