您的位置:首页 > 编程语言 > Java开发

再论JAVA中的核心数据——Map&Set

2012-11-12 14:08 369 查看
Map,顾名思义,是一种映射的机制

在JAVA中,常用的有Hashtable,HashMap,LinkedHashMap,TreeMap

Hashtable的大部分方法都做了同步,是线程安全的,HashMap是非线程安全的;而且Hashtable不允许key/value为Null,而HashMap可以

1、HashMap

HashMap底层的数据结构还是数组,内存地址就是数组的下标,HashMap中的哈希算法如下:

static int hash(int h) {
h ^= (h>>>20)^(h>>>12);
return h^(h>>>7)^(h>>>4);
}


^表示异或操作,>>>表示无符号右移

我们来看几个例子,大家就知道哈希算法的精妙之处了:

a=32768
a的二进制:1000000000000000
a的哈希值:35080
a的哈希值的二进制:1000100100001000
a=65536
a的二进制:10000000000000000
a的哈希值:70161
a的哈希值的二进制:10001001000010001
a=524288
a的二进制:10000000000000000000
a的哈希值:561289
a的哈希值的二进制:10001001000010001001
a=123456789
a的二进制:111010110111100110100010101
a的哈希值:119583776
a的哈希值的二进制:111001000001011010000100000


不知道大家有没有看出来这里的精妙,哈希算法的精髓就是平均分布,我们可以看到哈希值的二进制中的1已经平均分布了,这里采用位运算符而不采用逻辑运算符,也是为了性能的提升。

自己可以动手试试了。

那么以上是得到了key的哈希值了,那么下面,我们如何通过key来获取value呢?

static int indexFor(int h,int lengh) {
return h&(lengh-1);
}
通过将哈希值与数组最后一个元素下标做与运算,得到的值就是value的数组下标,直接获取即可。

学过数据结构的都知道,哈希存在冲突问题,那么如何解决呢?

HashMap是采用数组+链表的方式来实现,所以同一下标有多个数据元素的时候就在该下标形成了一个链表。。。

后来的元素不断插入在链表头部

HashMap=ArrayList+LinkedList

HashMap默认初始化大小是16,负载因子是0.75,

负载因子=元素个数/内部数组总大小,其实就是填充率

HashMap的扩容,同样会进行数组的整体复制,所以扩容操作要注意

2、LinkedHashMap

由于HashMap的无序性,从来出现了LinkedHashMap

是基于元素进入集合的顺序或被访问的先后顺序排序

3、TreeMap

是基于元素的固有顺序

实现Comparable接口,重写compareTo()方法

set

set的实现都只是对map的一种封装而已

RandomAccess

所有基于数组的List都实现了此接口,而基于链表的没有,很简单,只有数组才能快速定位访问某个元素,而链表需要遍历

所以在代码中,当需要查找元素操作时,你可以先判断list instanceof RandomAccess,使用不同的遍历操作

个人链接:

--------------------------------


新浪微博:http://weibo.com/cwtree

       

人人首页:www.renren.com/treelovexiaobei

       

优酷空间: http://i.youku.com/cwtree

       

科大首页:http://home.ustc.edu.cn/~cwtree/

--------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: