同步操作将从 Java精选/Ebooks 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
当类中要操作的引用数据类型不确定时,在JDK1.5版本前使用Object来完成扩展,JDK1.5后推荐使用泛型来完成扩展,同时保证安全性。
集合类接口指定了一组叫做元素的对象。集合类接口的每一种具体的实现类都可以选择以它自己的方式对元素进行保存和排序。有的集合类允许重复的键,有些不允许。
Java集合类提供了一套设计良好的支持对一组对象进行操作的接口和类。Java集合类里面最基本的接口有:
Collection:代表一组对象,每一个对象都是它的子元素。
Set:不包含重复元素的Collection。
List:有顺序的collection,并且可以包含重复元素。
Map:可以把键(key)映射到值(value)的对象,键不能重复。
HashMap默认长度16,扩容是2的n次方。
HashMap为了存取高效,要尽量较少碰撞,通俗的说就是要尽量把数据分配均匀,每个链表长度大致相同,这个实现就是要把数据存到哪个链表中的算法。
取模即hash%length,计算机中直接求余效率不如位移运算,JDK源码中做了相应的优化hash&(length-1),hash%length==hash&(length-1)的前提是length是2的n次方;
比如说10%8=2,10的二进制是1010,8的二进制是0100
0000 1010 0000 1000
这种取余操作对应2的幂次实际上也就是除数的值之前的数据被整除,后面的余数就是被除数剩余部分为1的值。
0000 1010除以0000 1000把0000 1000高位以及自己抹除,剩下0000 0010。换成与(&)的操作,就是把n(除数)-1和被除数,取余的结果“(n-1)&hash ”。
为什么这样可以均匀分布减少碰撞呢?
2的n次方实即为1后面有n个0,2的n次方-1即为n个1;
比如长度为9时,3&(9-1)=0 2&(9-1)=0 ,都在0上,碰撞了;
比如长度为8时,3&(8-1)=3 2&(8-1)=2 ,不同位置上,不碰撞。
其实就是按位“与”的时候,每一位都能&1,也就是和1111……1111111进行与运算。
Hash值的范围值-2147483648到2147483647,前后加起来大概40亿的映射空间,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。但问题是内存是无法存储这种量级别数组的,所以这个散列值是不能直接使用的。可以针对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“(n-1) & hash”。这也就解释了HashMap的长度为什么是2的幂次方。
JDK1.5版本引入了泛型,所有的集合接口和实现都大量地使用它。
类型安全,提供编译期间的类型检测。泛型允许为集合提供一个可以容纳的对象类型,如果添加其它类型的任何元素,它会在编译时报错,避免运行时出现异常ClassCastException。
泛型前后兼容。
泛化代码,代码可以更多的重复利用,泛型使得代码整洁,不需要使用显式转换和instanceOf操作符。
泛型性能比较高,用GJ(泛型Java)编写的代码可以为Java编译器和虚拟机带来更多的类型信息,这些信息对Java程序做进一步优化提供条件。
fail-fast机制,是一种错误检测机制。它只能被用来检测错误,因为JDK并不保证fail-fast机制一定会发生。若在多线程环境下使用fail-fast机制的集合,建议使用“java.util.concurrent包下的类”去取代“java.util包下的类”。
当多个线程对同一个集合进行操作时,某线程访问集合的过程中,该集合的内容被其他线程所改变,即其它线程通过add()、remove()、clear()等方法改变了modCount的值,此时就会抛出ConcurrentModificationException异常,产生fail-fast。
Iterator迭代器中fail-fast属性与当前的集合共同起作用,Iterator的安全失败是基于对底层集合做拷贝,因此它不会受到集合中任何改动的影响。
Java.util包中的所有集合类都快速失败的,即为被设计为fail-fast;而java.util.concurrent中的集合类都是安全失败的,即为fail-safe。
fail-fast事件产生是通过抛出ConcurrentModificationException异常,而fail-safe事件的产生从不抛出ConcurrentModificationException异常。
可以使用Collections包下的unmodifiableMap()方法,通过这个方法返回的map是不可以修改的。这样改变集合的任何操作都会抛出Java.lang.UnsupportedOperationException异常。
Collections包也提供了对list和set集合的方法。
Collections.unmodifiableList(List)
Collections.unmodifiableSet(Set)
也可以使用Collections.unmodifiableCollection(Collection c)方法来创建一个只读集合,这样改变集合的任何操作都会抛出Java.lang.UnsupportedOperationException异常。
示例代码:
List<String> list = new ArrayList<>();
list. add("微信公众号");
Collection<String> unmlist = Collections.unmodifiableCollection(list);
unmlist.add("Java精选"); // 运行时此行报错
System.out.println(list.size());
默认的负载因子大小为0.75,也就是指当一个map填满了75%的bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。
通俗的讲就是如果超过阙值会进行扩容操作,扩容后的数组大小是原数组的2倍,将原来的元素重新hashing放入到新的散列表中去。
Java中两个对象hashCode相等会产生哈希碰撞,若key值相同则替换旧值,不然链接到链表后面,链表长度超过阙值8就转为红黑树存储。
List
存储数据允许不唯一集合,可以有多个元素引用相同的对象且是有序的对象。
Set
不允许重复的集合,不存在多个元素引用相同的对象。
Map
使用键值对存储方式。Map维护与Key有关联的值。两个Key可以引用相同的对象,但Key不能重复,比如Key是String类型,但也可以是任何对象。
Set系列集合添加元素无序的根本原因是底层采用哈希表存储元素。
JDK1.8以下版本:哈希表 = 数组 + 链表 + (哈希算法)
JDK1.8及以上版本:哈希表 = 数组 + 链表 + 红黑树 + (哈希算法)
当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。