博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中HashMap和TreeMap
阅读量:3949 次
发布时间:2019-05-24

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

Java中HashMap和TreeMap

**HashMap 非线程安全 TreeMap 非线程安全 **

在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。这就是我们平时说的键值对。

HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。

线程安全

关于线程以及线程安全的相关知识有待笔者继续学习,敬请关注。

在Java里,线程安全一般体现在两个方面:

  1. 多个thread对同一个java实例的访问(read和modify)不会相互干扰,它主要体现在关键字synchronized。如ArrayList和Vector,HashMap和Hashtable
    (后者每个方法前都有synchronized关键字)。如果你在interator一个List对象时,其它线程remove一个element,问题就出现了。
  2. 每个线程都有自己的字段,而不会在多个线程之间共享。它主要体现在java.lang.ThreadLocal类,而没有Java关键字支持,如像static、transient那样

两种常规Map实现

HashMap:

基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()],为了优化HashMap空间的使用,您可以调优初始容量和负载因子。

(1)HashMap(): 构建一个空的哈希映像
(2)HashMap(Map m): 构建一个哈希映像,并且添加映像m的所有映射
(3)HashMap(int initialCapacity): 构建一个拥有特定容量的空的哈希映像
(4)HashMap(int initialCapacity, float loadFactor): 构建一个拥有特定容量和加载因子的空的哈希映像
HashMap的简单使用代码如下

package cn.my.collection;/** * 自定义hashmap * @author chenye * */public class MyHashMap {
Node2[] table; int size; public MyHashMap() {
table = new Node2[16]; } public void put(Object key,Object value) {
Node2 newNode=new Node2(); newNode.hash=myHash(key.hashCode(),table.length); newNode.key=key; newNode.value=value; newNode.next=null; } public static void main(String[] args) {
MyHashMap m=new MyHashMap(); m.put(10, "aa"); m.put(20, "ab"); m.put(30, "ac"); m.put(40, "ad"); } public int myHash(int v,int length ) {
System.out.println("hash in maHash"+(v&(length-1)));//直接位运算,效率高 System.out.println("hash in maHash"+(v%(length-1)));//取模运算,效率低 return v&(length-1); }}

HashMap是基于HashCode的,在所有对象的超类Object中有一个HashCode()方法,但是它和equals方法一样,并不能适用于所有的情况,这样我们就需要重写自己的HashCode()方法。

public class Exp2 {
public static void main(String[] args){
HashMap h2=new HashMap(); for (int i=0;i<10;i++) h2.put(new Element(i), new Figureout()); System.out.println("h2:"); System.out.println("Get the result for Element:"); Element test=new Element(5); if (h2.containsKey(test)) System.out.println((Figureout)h2.get(test)); else System.out.println("Not found"); }}class Element{
int number; public Element(int n){
number=n; }}class Figureout{
Random r=new Random(); boolean possible=r.nextDouble()>0.5; public String toString(){
if (possible) return "OK!"; else return "Impossible!"; }}

TreeMap:

基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。

(1)TreeMap():构建一个空的映像树
(2)TreeMap(Map m): 构建一个映像树,并且添加映像m中所有元素
(3)TreeMap(Comparator c): 构建一个映像树,并且使用特定的比较器对关键字进行排序
(4)TreeMap(SortedMap s): 构建一个映像树,添加映像树s中所有映射,并且使用与有序映像s相同的比较器排序

两种常规Map性能

HashMap:适用于在Map中插入、删除和定位元素。

Treemap:适用于按自然顺序或自定义顺序遍历键(key)。

总结

HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。

在HashMap中通过get()来获取value,通过put()来插入value,ContainsKey()则用来检验对象是否已经存在。可以看出,和ArrayList的操作相比,HashMap除了通过key索引其内容之外,别的方面差异并不大。

前面介绍了,HashMap是基于HashCode的,在所有对象的超类Object中有一个HashCode()方法,但是它和equals方法一样,并不能适用于所有的情况,这样我们就需要重写自己的HashCode()方法。

如果你想有效的使用HashMap,你就必须重写在其的HashCode()。

*** 还有两条重写HashCode()的原则:***

不必对每个不同的对象都产生一个唯一的hashcode,只要你的HashCode方法使get()能够得到put()放进去的内容就可以了。即"不为一原则"。

生成hashcode的算法尽量使hashcode的值分散一些,不要很多hashcode都集中在一个范围内,这样有利于提高HashMap的性能。即"分散原则"。

对于哈希表的和散列表的相关理解可以参照数据结构。

转载地址:http://jogwi.baihongyu.com/

你可能感兴趣的文章
linux学习之查找文件find,locate,whereis使用
查看>>
JS中$含义及用法
查看>>
web学习之ajax记录
查看>>
web学习之ajax参数解析
查看>>
linux学习之curl命令使用
查看>>
java模板引擎中主要三个JSP,Freemarker,Velocity简述
查看>>
javascript学习之$(function() {})
查看>>
kafka初识
查看>>
mysql存储过程 --游标的使用 取每行记录
查看>>
ranger通过web界面登录用户验证类UsernamePasswordAuthenticationFilter
查看>>
墨菲定律——生活
查看>>
墨菲定律——职场
查看>>
mysql学习使用二(更新)
查看>>
java匿名内部类原理及使用
查看>>
java基础学习之Timer定时器使用
查看>>
Linux中修改环境变量及快速生效方法
查看>>
Linux学习 - vi/vim 编辑器显示行号
查看>>
linux 卸载python
查看>>
Linux下安装Python2.7与升级至2.7
查看>>
winscp连接linux虚拟机失败
查看>>