博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Java编程思想》之对象的集合(数组、List、Set、Map)二
阅读量:5124 次
发布时间:2019-06-13

本文共 2903 字,大约阅读时间需要 9 分钟。

上接:

22、使用自己创建的类作为HashMap的“键”,需要同时覆盖hashCode()和equals()。原因如下:

1).默认的hashCode()继承自Object,它默认是使用对象的地址计算散列码。

因此即使俩个对象的实例的内容相同,对象的地址是不同的,所以默认的hashCode()得到的散列码是不同的。如下例子:

import java.util.HashMap; import java.util.Map; public class TestHashMap{ private int id; public TestHashMap(int id){ this.id = id; } public void func(){ System.out.println(id); } public String toString(){ return "TestHashcode#" + id; } public static void main(String[] args){ TestHashMap testHashcode = new TestHashMap(2012); Map<Object, Object> hashMap = new HashMap<Object, Object>(); hashMap.put(testHashcode, 2012); if(hashMap.containsKey(testHashcode)){ System.out.println("找到id为:" + testHashcode.id+"的TestHashcode"); } else{ System.out.println("找不到id为:" + testHashcode.id+"的TestHashcode"); } TestHashMap testHashcode1 = new TestHashMap(2012); if(hashMap.containsKey(testHashcode1)){ System.out.println("找到id为:" + testHashcode1.id+"的TestHashcode"); } else{ System.out.println("找不到id为:" + testHashcode1.id+"的TestHashcode"); } System.out.println("--------------------------------"); System.out.println("testHashcode散列码为:"+testHashcode.hashCode()); System.out.println("testHashcode1散列码为:"+testHashcode1.hashCode()); } }

运行结果:

出现了“找到”“找不到”这种尴尬的处境。

2).这时,自己覆盖Oject的hashCode(),在TestHashMap中添加:

public int hashCode(){ return id; }

再运行,结果如下:

 

3).这是因为HashMap使用equals()判断当前的“键”是否与表中存在的“键”相同,而默认equals()是继承自Object, Object中的Object.equals()只是比较对象的地址。于是再向TestHashMap添加:

public boolean equals(Object o){ // o instanceofTestHashMap检查o是否是TestHashMap的实例 return (o instanceof TestHashMap) && (id == ((TestHashMap)o).id); }

运行结果:

综上:自定义的类,如果不为“键”覆盖hashCode()和equals(),那么在使用散列的数据结构是(HashSet、HashMap、LinkedHashSe,或LinkedHashMap),就无法正确处理你的“键“。

23、散列的价值在于速度:散列使得查询得以快速进行。由于瓶颈位于“键“的查询速度,散列使用数组(存储一组元素最快的数据结构)来保存散列”键“信息。数组并不保持”键“本身,而是通过”键“对象生成一个数字,将其作为数组的小标。这个数字就是散列码,由定义在Object中的。且可能由你的类覆盖的hashCode()生成。为解决数组容量被固定的问题,不同的”键“可以产生相同的下标,出现冲突。

24、查询一个“值“:计算散列码,使用散列码查询数组。出现冲突,由“外部链接“处理,这时数组并不是直接保存”值“,而是保存”值“的list。然后对list中的”值“使用equals()方法进行线性的查询。

25、ArrayList底层由数组支持,而LinkedList是由双向链表实现的。因此,如果经常要在表中插入和删除元素,LinkedList就比较适合(LinkedList还有建立在AbstractSequentialList基础上的其他功能);否则,应该使用速度更快的ArrayList。

26、树的行为方式是:它总是处于排序状态。TreeSet、HashMap都是排序好的。

27、只有在执行binarySearch()之前,才确实需要对List或数组进行排序。

28、总结:

1). 数组将数字与对象联系起来。它保存类型明确的对象,查询对象时,不需要对结果做类型转换。它可以是多维的,可以保存基本类型的数据。但是,数组一旦生成,其容量就不能改变。

2).Collection保存单个的元素,而Map保存相关联的键值对。
3).像数组一样,List也建立数字与对象的关联,可以认为数组和List都是排好序的容器。List能够自动扩充容量。但是List不能保存基本类型,只能保存Object的引用,因此必须对从容器中取出的Object结果做类型转换(RTTI)。
4).如果要进行大量的随机访问,就使用ArrayList;如果要经常从List中间插入或删除元素,则应该使用LinkedList。

5). 队列、双向队列以及栈的行为,由LinkedList提供支持。

6).Map是一种将对象与对象相关联的设计。HashMap着重于快速访问;TreeMap保持“键”始终处于排序状态,所以没有HashMap快。LinkedHashMap保持元素插入的顺序,也可以使用LRU(“最近最少使用“)算法对其重排序

7). Set不接受重复元素。HashSet提供最快的查询速度,TreeSet保持元素处于排序状态。LinkedHashSet以插入顺序保存元素。
8).新程序中不应该使用过时的Vector、Hashtable和Stack。

以上内容整理自《Java编程思想》,若有遗漏,请您不吝指出!

转载于:https://www.cnblogs.com/myittec/archive/2012/02/03/2392764.html

你可能感兴趣的文章
Java泛型的基本使用
查看>>
1076 Wifi密码 (15 分)
查看>>
noip模拟赛 党
查看>>
bzoj2038 [2009国家集训队]小Z的袜子(hose)
查看>>
Java反射机制及其Class类浅析
查看>>
Postman-----如何导入和导出
查看>>
移动设备显示尺寸大全 CSS3媒体查询
查看>>
图片等比例缩放及图片上下剧中
查看>>
【转载】Linux screen 命令详解
查看>>
background-clip,background-origin
查看>>
Android 高级UI设计笔记12:ImageSwitcher图片切换器
查看>>
【Linux】ping命令详解
查看>>
对团队成员公开感谢博客
查看>>
java学习第三天
查看>>
python目录
查看>>
django+uwsgi+nginx+sqlite3部署+screen
查看>>
Andriod小型管理系统(Activity,SQLite库操作,ListView操作)(源代码下载)
查看>>
在Server上得到数据组装成HTML后导出到Excel。两种方法。
查看>>
浅谈项目需求变更管理
查看>>
经典算法系列一-快速排序
查看>>