jdk8源码解析第一天(简化版,只记自己理解的要点)

1.String类:

实现了serilizable,comparable接口,seriliazable仅用于标志,comparable的comparableTo方法用于比较字符串大小。

底层是通过final char[] 实现字符串的,其所有方法均是用字符数组相关方法实现的。

2.ArrayList:

实现了List,RandomAccess,Clone,serilizable接口,ArrayList底层由动态数组实现,初始数组长度为0,当第一次添加元素时就会扩容到10,也可以调用者自己赋初始数组容量。(调用者如果赋初始容量,那初始容量最小为10,即(调用者赋值小于10则初始容量为10).当添加元素到集合大小时扩容到1.5倍。其他ArrayList集合方法效率和数组特性有关,比如remove方法,需要删除指定位置的元素,将其后的元素向前移位,这时间复杂度很大的事,所以效率低,同样的在指定位置插入元素效率同样低。这就是我们说的ArrayList集合可以快速改查,但是增删效率低下。

ArrayList是线程不安全的原因:当集合add元素时,由需要执行两步,第一判断集合容量是否能容下该元素,然后再添加元素,比如集合容量初始容量为10,当集合恰好到9时,一个线程判断集合容量可进行add操作,然后另一个线程又进行了判断可进行add操作,当两个线程都进行了add操作,数组就越界了。还有一种就是当一个线程判断容量后和另一个线程也判断了容量同时进行插入时,会将数组的一个角标位赋两次值,后一次会覆盖前一次,导致添加了了两次而集合只添加了一个元素。

object 的toArray()方法可能会出异常的,这是因为多态导致的object[]数组中可能存的是object子类,当其用toArray()方法时,返回的就是其子类数组,导致object向下转型,而向下转型是有可能会出错的。

3.LinkedList:

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

LinkedList 是线程不安全的。

LinkedList的访问特定位置元素,是利用类似折半查找的方法。因为双向链表只有前驱后继是没有角标的,想要查找到特定位置,只能遍历。

LinkedList可以快速增删,这和链表的特有性关,再增加或删除一个元素时,只需改变其和相邻的元素的前驱后继。

4.HashSet:

HashSet是基于HashMap实现的,key为出入元素的HashCode,value为存入的元素,因为HashMap的key值不能重复,所以得到了HashSet的不可存入重复元素的特性。所以其特性通过HashMap即可了解。HashSet线程不安全。

5.HashMap:

HashMap以Entry数组和链表组成的,Entry有四个属性,key,value,nextEntry,hashCode组成。如下图,补充一点,当一个链表长度大于8时,后面存入的数据就会采用红黑树的方式,加快检索方式。

HashMap初始容量为16,每次扩容加倍,负载因子为0.75,容量为2的倍数是为了保证低位的散列均匀。

key ---hashCode()---> hashCode ---hash()---> h --- indexFor() ---> Entry[]下标,hashCode()方法是计算key的hashCode值,hash()方法是将key的hashCode值转化成一个实际的数字(将hashCode>>>16再与hashCode按位异或)得到一个hash值,indexFor()方法内部是用h和数组长度-1进行按位与操作,即得到了Entry下标。为了让Entry数组每个链表尽量均匀分布,所以hashMap的容量为2的倍数。

有理解不对的地方欢迎大家多多指正。

猜你喜欢

转载自blog.csdn.net/You_are_my_Mr_Right/article/details/83241953
今日推荐