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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://xxlcube.blog.csdn.net/article/details/8172994

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,使用不同的遍历操作


个人链接:
--------------------------------
JavaMail实现(JAVA <wbr><wbr><wbr>SWING)新浪微博:http://weibo.com/cwtree

       JavaMail实现(JAVA <wbr><wbr><wbr>SWING)人人首页:www.renren.com/treelovexiaobei

       JavaMail实现(JAVA <wbr><wbr><wbr>SWING)优酷空间: http://i.youku.com/cwtree

       JavaMail实现(JAVA <wbr><wbr><wbr>SWING)科大首页:http://home.ustc.edu.cn/~cwtree/
--------------------------------



展开阅读全文

没有更多推荐了,返回首页