最近学了JAVA之后,对JAVA源码实现很感兴趣,于是就在自己的Eclipse里看JAVA里的一些常用的类的源码实现,自己水平也不是很高,有不懂的代码还是要去看别人写的博客,我写的这篇文章也是看了别人的博客后,加上自己看了源码后的理解而作,既是希望自己能从此掌握这两个类的实现,也能帮助那些渴望成为编程大牛的孩子。大家有不理解的可以看这篇文章 https://www.baidu.com/link?url=IqZUK4wSjRAZ-yDH2wgp_x3uosAcN1bFUv7GYaQk4DStjeU559QtWuUsHAu9WViOKJXaaW3qJnBJv3KH9jRI2nhOdw-zjOi-GA4OspLHYUK&wd=&eqid=cf09827d00034226000000035991cae8
HashMap和HashSet是java里很常用的两个类,他们有
相同之处
1:都是用Hash算法来存储元素的值
2:查找存取的性能都很好(当然比数组还是稍微差一些)
3:存储的值都允许为null
4:都不是线程安全的
5:都不维护元素的顺序,也就是说,是乱序存放的
6:都是collection框架的一部分
不同之处
1:HashSet里的value不允许重复,但是HashMap的value是允许重复的
2:HashMap是以键值对来存储的,而HashSet仅仅是存放值
3:HashMap实现的是Map接口,HashSet实现的是Set接口
4:HashMap使用键对象来计算Hashcode,HashSet使用值对象来计算hashcode(因为它只存放值,所以只能用值来计算hashcode)
下面就是具体的分析源码了,先把源码贴上,我们边看源码边分析。先分析HashMap(hashmap的实现原理图接我建议先看这篇博文,我觉得讲的很清楚 http://blog.csdn.net/eson_15/article/details/51158865?locationNum=2&fps=1)
/*HashMap 继承的是AbstractMap,它实现了Map, Cloneable, Serializable 三个类*/
public class HashMap extends AbstractMap
implements Map, Cloneable, Serializable
{
/*DEFAULT_INITIAL_CAPACITY = 16 默认容量为16*/
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final int MAXIMUM_CAPACITY = 1073741824;
/*默认的负载因子的值*/
static final float DEFAULT_LOAD_FACTOR = 0.75F;
/*说一下 transient 。transient是Java语言的关键字,用来表示一个域不象串行化的一部分。当持久化对象时,可能有一个特殊的对象数据成员,我们不想serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。然而非transient型的变量是被包括进去的。*/
transient Entry[] table;/* table 是Entry[]数组变量,也就是键值对类型的数组,一个可以对应一个value*/
transient int size;
int threshold; /* 极限容量*/
final float loadFactor; /*负载因子*/
transient volatile int modCount; /*用来记录对map的操作次数,这个变量特别重要*/
private transient Set entrySet = null;
private static final long serialVersionUID = 362498820763181265L;
/*静态的Entry类,实现Map.Entry,里面就定义了,key,value,next,hash我们需要用的变量,key,value不说了,next变量相当于一个指针,在用 Iterator 遍历时会发挥很大的作用*/
static class Entry implements Map.Entry
{
final Object key;
Object value;
Entry next;
final int hash;
/*Entry 的构造函数*/
Entry(int i, Object object, Object object_0_, Entry entry_1_) {
value = object_0_;
next = entry_1_;
key = object;
hash = i;
}
/*得到map里存储的key值*/
public final Object getKey() {
return key;
}
/*得到value值*/
public final Object getValue() {
return value;
}
/*设置value值*/
public final Object setValue(Object object) {
Object object_2_ = value; /*用一个变量来保存旧的值*/
value = object; /*设置新的值*/
return object_2_; /*返回旧值*/
}
/*判断两个对象是否相等的方法*/
public final boolean equals(Object object) {
if (!(object instanceof Map.Entry))
return false; /*首先判断类型是否相等,不相等直接返回false*/
/*强制转换object为Entry对象类型,用entry_3_ 变量表示*/
Map.Entry entry_3_ = (Map.Entry) object;
Object object_4_ = getKey(); /*用getKey方法得到key值(这是用equals方法的那个对象的key值,而不是object的key值)*/
/*这才是object的key值,entry_3_ 表示的就是object*/
Object object_5_ = entry_3_.getKey();
/*判断key值是否相等(object_4_ == object_5_), (object_4_ != null && object_4_.equals(object_5_))key值不能为null且要相等,否则就没必要比较value值了*/
if (object_4_ == object_5_
|| object_4_ != null && object_4_.equals(object_5_)) {
/*就可以比较value值是否相等,逻辑与比较key值相同*/
Object object_6_ = getValue();
Object object_7_ = entry_3_.getValue();
if (object_6_ == object_7_
|| object_6_ != null && object_6_.equals(object_7_))
return true;
}
return false;
}
/*根据key值和value值来计算hash值,来定位此对象在hashmap中的位置*/
public final int hashCode() {
return ((key == null ? 0 : key.hashCode())
^ (value == null ? 0 : value.hashCode()));
}
/*toString() 方法,没什么好说的*/
public final String toString() {
return new StringBuilder().append(getKey()).append("=").append
(getValue()).toString();
}
void recordAccess(HashMap hashmap) {
/* empty */
}
void recordRemoval(HashMap hashmap) {
/* empty */
}
}
/*内部类,定义EntryIterator 迭代器和一些其他方法,是可以被hashmap类直接访问的,从名字可以知道,它是用来迭代Entry类型对象的迭代器*/
private final class EntryIterator extends HashIterator
{
final HashMap this$0 = HashMap.this; (HashMap.this表示引用的是HashMap这个类的实例,不这样声明编译器会不知道引用的是哪个实例)
/*直接继承父类的EntryIterator()*/
private EntryIterator() {
super();
}
/*next()方法,迭代器时会使用,是实现迭代器的重要方法*/
public Map.Entry next() {
return nextEntry();
}
public volatile Object next() {
return next();
}
EntryIterator(ANONYMOUS CLASS java.util.HashMap$1 var_1) {
this();
}
}
/*EntrySet类,将Entry对象封装成一个Set,这样可以用来作遍历hashmap集合,速度很快*/
private final class EntrySet extends AbstractSet
{
final HashMap this$0 = HashMap.this;
/*使用父类的构造函数*/
private EntrySet() {
super();
}
/*EntrySet的迭代器*/
public Iterator iterator() {
return this$0.newEntryIterator();
}
/*判断是否包含此object对象*/
public boolean contains(Object object) {
if (!(object instanceof Map.Entry))
return false; /*同样是先判断类型是否相等*/
Map.Entry entry = (Map.Entry) object;
/*通过getEntry()方法通过entry.getKey()得到Entry对象*/
Entry entry_8_ = this$0.getEntry(entry.getKey());
/*调用之前的equals方法来判断是否相等,相等则返回true*/
return entry_8_ != null && entry_8_.equals(entry);
}
/*调用hashmap.removeMapping(object)方法,如果成功删除,则放回true,否则object不在keyset里,则放回false*/
public boolean remove(Object object) {
return this$0.removeMapping(object) != null;
}
/*整个map的大小*/
public int size() {
return this$0.size;
}
/*调用hashmap的clear()方法,这个方法在下面会说到*/
public void clear() {
this$0.clear();
}
EntrySet(ANONYMOUS CLASS java.util.HashMap$1 var_1) {
this();
}
}
/*真正到了重要的地方,这个类特别重要,也是个迭代类,是内部抽象类,这个类的方法常常拿来做hashmap的迭代*/
private abstract class HashIterator implements Iterator
{
Entry next; /*entry类型的变量,是用来保存下一个迭代对象的 指针 */
int expectedModCount; /* 这个int 型变量是跟前面 modCount 对应的,他们一定要相等,不然就会报错,他们是用来记录对map集合的操作次数,即增删改的次数*/
int index; /*hash 下标,标识map中元素的位置*/
Entry current; /*迭代过程中当前的迭代对象*/
final HashMap this$0 = HashMap.this; /* 要记得它还是当前这个hashmap的引用实例*/
/*构造函数 注意 expectedModCount = modCount; 是要相等的 */
HashIterator() {
super();
expectedModCount = modCount;
if (size > 0) {
Entry[] entrys = table;
while (index < entrys.length
&& (next = entrys[index++]) == null) {
/* empty */ /*为什么里面是空的,我也不是太清楚,我看别人博客说的是,这是为了让你自己写你需要的实现,while里的条件也不难理解*/
}
}
}
/* hasNext 方法,是不是很简单?只要还有next指针,就可以继续遍历,否则返回false*/
public final boolean hasNext() {
return next != null;
}
/*这个类返回Entry类型的对象 */
final Entry nextEntry() {
/ * 先判断modCount == expectedModCount 是否相等,如果不等,就会抛出异常 ConcurrentModificationException()*/
if (this$0.modCount != expectedModCount)
throw new ConcurrentModificationException();
/*将next对象赋给 entry变量*/
Entry entry = next;
/*判断是否为null,为null表示没有这个元素存在map里*/
if (entry == null)
throw new NoSuchElementException();
/*以上的判断都通过了,就可以真正进行nextEntry 的判断了,(next = entry.next) == null 因为 hashmap里存放数据是不连续的,如果下一个指针所指的entry对象为null,就通过下面的代码来找到下一个不为null的对象,当entry.next为空时,就要循环找到下一个不为空的entry对象,entry.next不为null,则会跳过这段代码*/
if ((next = entry.next) == null) {
Entry[] entrys = this$0.table;
/*while 的作用,当遇到不为null的entry对象就跳出循环,并且赋给了 next 指针 要是一直是null,那么next指针也是null,index标识当前entry对象在进入循环时的位置,并且会执行index++操作*/
while (index < entrys.length
&& (next = entrys[index++]) == null) {
/* empty */
}
}
/*当前迭代的对象是entry*/
current = entry;
return entry; /*返回entry*/
}
/* 删除操作*/
public void remove() {
/*当前要删除的对象不能为null*/
if (current == null)
throw new IllegalStateException();
/*modCount ,expectedModCount 一定要相等*/
if (this$0.modCount != expectedModCount)
throw new ConcurrentModificationException();
/*先得到key*/
Object object = current.key;
/*将它设为null,这样GC就会回收它*/
current = null;
/*调用此方法,就能以key来删除 entry对象*/
this$0.removeEntryForKey(object);
/*删除操作后要再次令 expectedModCount = this$0.modCount*/
expectedModCount = this$0.modCount;
}
}
/*这是以key来作迭代的 内部类,继承 HashIterator 原理都差不多*/
private final class KeyIterator extends HashIterator
{
final HashMap this$0 = HashMap.this;
private KeyIterator() {
super();
}
/*得到下一个key*/
public Object next() {
return nextEntry().getKey();
}
KeyIterator(ANONYMOUS CLASS java.util.HashMap$1 var_1) {
this();
}
}
/* keyset 也就是所有的key的集合,也可以拿来遍历map的key的集合*/
private final class KeySet extends AbstractSet
{
final HashMap this$0 = HashMap.this;
private KeySet() {
super();
}
public Iterator iterator() {
return this$0.newKeyIterator();
}
public int size() {
return this$0.size;
}
/*调用containsKey(object) 来判断是否包含,containsKey(object) 在后面会说*/
public boolean contains(Object object) {
return this$0.containsKey(object);
}
/*同上的remove方法的逻辑*/
public boolean remove(Object object) {
return this$0.removeEntryForKey(object) != null;
}
public void clear() {
this$0.clear();
}
KeySet(ANONYMOUS CLASS java.util.HashMap$1 var_1) {
this();
}
}
/*同keyIterator 的实现原理和思路*/
private final class ValueIterator extends HashIterator
{
final HashMap this$0 = HashMap.this;
private ValueIterator() {
super();
}
public Object next() {
return nextEntry().value;
}
ValueIterator(ANONYMOUS CLASS java.util.HashMap$1 var_1) {
this();
}
}
private final class Values extends AbstractCollection
{
final HashMap this$0 = HashMap.this;
private Values() {
super();
}
public Iterator iterator() {
return this$0.newValueIterator();
}
public int size() {
return this$0.size;
}
public boolean contains(Object object) {
return this$0.containsValue(object);
}
public void clear() {
this$0.clear();
}
Values(ANONYMOUS CLASS java.util.HashMap$1 var_1) {
this();
}
}
/*终于找到hashmap的构造方法了。i 是设置 entry[] 数组的大小, i不能小于0,也不能大于1073741824,f是负载因子的大小*/
public HashMap(int i, float f) {
if (i < 0)
throw new IllegalArgumentException
(new StringBuilder().append
("Illegal initial capacity: ").append
(i).toString());
if (i > 1073741824)
i = 1073741824;
if (f <= 0.0F || Float.isNaN(f))
throw new IllegalArgumentException(new StringBuilder().append
("Illegal load factor: ")
.append
(f).toString());
int i_9_;
for (i_9_ = 1; i_9_ < i; i_9_ <<= 1) {
/* empty */
}
loadFactor = f;
threshold = (int) ((float) i_9_ * f);
table = new Entry[i_9_];
/*初始化的方法,是空的*/
init();
}
/*这个大家都能看懂吧*/
public HashMap(int i) {
this(i, 0.75F);
}
/*默认的构造方法,如果不加参数,就默认这么设置*/
public HashMap() {
loadFactor = 0.75F;
threshold = 12;
table = new Entry[16];
init();
}
/*这个构造方法比较复杂,好像也不常用*/
public HashMap(Map map) {
this(Math.max((int) ((float) map.size() / 0.75F) + 1, 16), 0.75F);
/*注意这个方法,后面会说到*/
putAllForCreate(map);
}
void init() {
/* empty */
}
/*这就是计算hash值的方法,想深入研究的可以去查查实现原理,我不是太懂*/
static int hash(int i) {
i ^= i >>> 20 ^ i >>> 12;
return i ^ i >>> 7 ^ i >>> 4;
}
/*这个方法计算出该entry对象在table数组里存放的位置, i_10_ 变量将要存的是table数组的长度,传入table数组的长度就不会使计算出的位置超越数组的长度*/
static int indexFor(int i, int i_10_) {
return i & i_10_ - 1;
}
public int size() {
return size;
}
/*这个方法也是很简单的,size大于0,就不是空的*/
public boolean isEmpty() {
return size == 0;
}
/*get方法会根据object(实际上它是key的值)得到所存贮的值*/
public Object get(Object object) {
if (object == null) /*为null时,用getForNullKey() 方法得到它的值*/
return getForNullKey();
int i = hash(object.hashCode()); /*得到hash值,即索引*/
/*用for循环来循环此table[indexFor(i, table.length)]处是否存在链表,有链表则遍历找出要找的key和它的值*/
for (Entry entry = table[indexFor(i, table.length)]; entry != null;
entry = entry.next) {
Object object_11_;
/*if条件里是要对比key值和计算出的hash值的,最后还得用equals方法进行比较,才能真正返回value值*/
if (entry.hash == i && ((object_11_ = entry.key) == object
|| object.equals(object_11_)))
return entry.value;
}
return null;
}
/*当key为空时,调用此方法得到对应value*/
private Object getForNullKey() {
/*为什么从0开始遍历呢?因为hashmap里默认将key=null的key-value对放在table[0]处,for循环用来检查是否有链表存在,有则遍历得到第一个key为null的值*/
for (Entry entry = table[0]; entry != null; entry = entry.next) {
if (entry.key == null)
return entry.value;
}
return null;
}
/*通过key值来判断此key是否包含在table数组里*/
public boolean containsKey(Object object) {
return getEntry(object) != null;
}
/*getEntry方法,很重要,在很多方法里都调用了它*/
final Entry getEntry(Object object) {
/*首先还是先计算它的hash值,它是用来在indexFor(i, table.length)方法里定位此key在table数组里的地址的*/
int i = object == null ? 0 : hash(object.hashCode());
/*此for循环的作用和之前的一样,大家很容易看懂的*/
for (Entry entry = table[indexFor(i, table.length)]; entry != null;
entry = entry.next) {
Object object_12_;
if (entry.hash == i
&& ((object_12_ = entry.key) == object
|| object != null && object.equals(object_12_)))
return entry;
}
return null;
}
/*hashmap里的put方法,大家经常用,现在看看是怎么实现的*/
public Object put(Object object, Object object_13_) {
/*先判断key是否为空,为空则用另外的方法来put它,即putForNullKey(object_13_) 方法*/
if (object == null)
return putForNullKey(object_13_);
/*一样得到hash值*/
int i = hash(object.hashCode());
int i_14_ = indexFor(i, table.length); /*定位在table数组的位置*/
/*判断此位置是否有链表,此段代码会判断是否已经有相同的key值存在,如果已经有了,会覆盖value值,没有则会在此位置插入一个entry对象*/
for (Entry entry = table[i_14_]; entry != null; entry = entry.next) {
Object object_15_;
if (entry.hash == i && ((object_15_ = entry.key) == object
|| object.equals(object_15_))) {
Object object_16_ = entry.value;
entry.value = object_13_; /*替换value值*/
entry.recordAccess(this);
return object_16_; /*会返回旧值*/
}
}
/*如果没有已经存在的key值,会直接执行下面的代码*/
modCount++; /*操作标识数+1*/
addEntry(i, object, object_13_, i_14_); /*新加了一个entry对象*/
return null;
}
/*当key值为空时,object代表的要插入的value值*/
private Object putForNullKey(Object object) {
for (Entry entry = table[0]; entry != null; entry = entry.next) { /*也替换key为null的entry对象的value值*/
if (entry.key == null) {
Object object_17_ = entry.value;
entry.value = object;
entry.recordAccess(this);
return object_17_;
}
}
/*前面的代码执行后没有找到null的key,则新插入一个新entry对象*/
modCount++;
addEntry(0, null, object, 0);
return null;
}
/*这个方法实现原理和前面的方法相同*/
private void putForCreate(Object object, Object object_18_) {
int i = object == null ? 0 : hash(object.hashCode());
int i_19_ = indexFor(i, table.length);
for (Entry entry = table[i_19_]; entry != null; entry = entry.next) {
Object object_20_;
if (entry.hash == i
&& ((object_20_ = entry.key) == object
|| object != null && object.equals(object_20_))) {
entry.value = object_18_;
return;
}
}
createEntry(i, object, object_18_, i_19_);
}
/*和上面的putAllForCreate方法是同一个方法,只是传入的是map*/
private void putAllForCreate(Map map) {
/*用iterator迭代器来迭代entrySet()集合里的entry对象*/
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
putForCreate(entry.getKey(), entry.getValue());
}
}
/*重置table数组的大小*/
void resize(int i) {
Entry[] entrys = table;
int i_21_ = entrys.length;
if (i_21_ == 1073741824)
threshold = 2147483647; /*threshold=i_21*2-1 ,即如果table数组的大小已经达到1073741824了,就扩容*/
else {
/ *不然,就按传入的i来重新创建Entry[]数组*/
Entry[] entrys_22_ = new Entry[i];
transfer(entrys_22_); /*此方法是重新复制table数组*/
table = entrys_22_; /*将entrys_22_新数组的引用地址赋给table数组*/
threshold = (int) ((float) i * loadFactor);
}
}
/*这就是上面的transfer方法的实现*/
void transfer(Entry[] entrys) {
Entry[] entrys_23_ = table; /*这是没复制前的table*/
int i = entrys.length;
/*for循环遍历table,并将table里的entry对象存入entrys数组里*/
for (int i_24_ = 0; i_24_ < entrys_23_.length; i_24_++) {
Entry entry = entrys_23_[i_24_];
if (entry != null) {
entrys_23_[i_24_] = null; /*将它变成null*/
do {
Entry entry_25_ = entry.next;
int i_26_ = indexFor(entry.hash, i); /*定位在entrys数组里的位置*/
entry.next = entrys[i_26_];
entrys[i_26_] = entry; /*复制操作,将entry赋给entrys[i_26_]*/
entry = entry_25_; /*将原来的entry.next赋给entry,用来作while循环*/
} while (entry != null);
}
}
}
/*将map里的对象全放进hashmap里*/
public void putAll(Map map) {
int i = map.size(); /*判断map的对象的多少*/
/*对i的值进行判断,这是有必要的*/
if (i != 0) {
if (i > threshold) {
int i_27_ = (int) ((float) i / loadFactor + 1.0F);
if (i_27_ > 1073741824)
i_27_ = 1073741824;
int i_28_;
for (i_28_ = table.length; i_28_ < i_27_; i_28_ <<= 1) {
/* empty */
}
if (i_28_ > table.length)
resize(i_28_);
}
/*用迭代器来迭代put每一个元素进hashmap*/
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
put(entry.getKey(), entry.getValue());
}
}
}
/*删除操作*/
public Object remove(Object object) {
Entry entry = removeEntryForKey(object);
return entry == null ? null : entry.value;
}
/*删除操作具体实现*/
final Entry removeEntryForKey(Object object) {
/*得到hash值*/
int i = object == null ? 0 : hash(object.hashCode());
int i_29_ = indexFor(i, table.length); /*table
数组里object key值对应的地址*/
Entry entry = table[i_29_]; /*得到key对应的那个对象*/
Entry entry_30_;
Entry entry_31_;
/*还是在遍历当前位置是否有链表存在,有的话就遍历判断*/
for (entry_31_ = entry; entry_31_ != null; entry_31_ = entry_30_) {
entry_30_ = entry_31_.next; /*entry_30_存链表上当前entry对象的下一个对象的指针*/
Object object_32_;
if (entry_31_.hash == i
&& ((object_32_ = entry_31_.key) == object
|| object != null && object.equals(object_32_))) {
modCount++; /*删除操作后要modCount++*/
size--; /*大小要减一*/
if (entry == entry_31_) /*如果要删除的是当前的第一个entry对象*/
table[i_29_] = entry_30_; /*则将entry_31_.next存在table[i_29_]中,即将原来是在链表头的entry对象的下一个对象移到表头来,因为当前在表头的entry对象要被删除了*/
else
entry.next = entry_30_; /*不是当前的第一个entry对象*/
entry_31_.recordRemoval(this);
return entry_31_;
}
entry = entry_31_;
}
return entry_31_; /*返回删除的entry对象的value*/
}
/*和上面的removeEntryForKey 原理类似*/
final Entry removeMapping(Object object) {
if (!(object instanceof Map.Entry)) /*先判断类型是否相同*/
return null;
Map.Entry entry = (Map.Entry) object; /*此传入的object就是一个对象类型了,强制转换成entry类型*/
Object object_33_ = entry.getKey(); /*得到key*/
/*得到hash值*/
int i = object_33_ == null ? 0 : hash(object_33_.hashCode());
/*得到在table数组里的定位*/
int i_34_ = indexFor(i, table.length);
Entry entry_35_ = table[i_34_];
Entry entry_36_;
Entry entry_37_;
/*实现原理和上面的方法一致,就不细说了*/
for (entry_37_ = entry_35_; entry_37_ != null; entry_37_ = entry_36_) {
entry_36_ = entry_37_.next;
if (entry_37_.hash == i && entry_37_.equals(entry)) {
modCount++;
size--;
if (entry_35_ == entry_37_)
table[i_34_] = entry_36_;
else
entry_35_.next = entry_36_;
entry_37_.recordRemoval(this);
return entry_37_;
}
entry_35_ = entry_37_;
}
return entry_37_;
}
/*clear方法,遍历table数组将每一个entry对象置为null,等待虚拟机将其回收*/
public void clear() {
modCount++;
Entry[] entrys = table;
for (int i = 0; i < entrys.length; i++)
entrys[i] = null;
size = 0; /*将size置为0*/
}
/*object代表的是value的值*/
public boolean containsValue(Object object) {
if (object == null)
return containsNullValue();
Entry[] entrys = table;
/*用两个for循环来遍历,其实效率不高啦*/
for (int i = 0; i < entrys.length; i++) {
/*防止有出现链表的情况,所以在每个table数组的位置在遍历一次,逐个对比*/
for (Entry entry = entrys[i]; entry != null; entry = entry.next) {
if (object.equals(entry.value))
return true; /*找到则返回true*/
}
}
return false;
}
/*当传进来的value等于null时调用这个方法,原理和上面的方法一致*/
private boolean containsNullValue() {
Entry[] entrys = table;
for (int i = 0; i < entrys.length; i++) {
for (Entry entry = entrys[i]; entry != null; entry = entry.next) {
if (entry.value == null)
return true;
}
}
return false;
}
/*用来克隆的方法,此方法比较简单*/
public Object clone() {
HashMap hashmap_38_ = null;/*新创建一个hashmap对象*/
try {
hashmap_38_ = (HashMap) super.clone();
} catch (CloneNotSupportedException clonenotsupportedexception) {
/* empty */
}
hashmap_38_.table = new Entry[table.length];/*创建一个新的table*/
hashmap_38_.entrySet = null;
hashmap_38_.modCount = 0; /*将它设为0是因为putAllForCreate(this)方法会在内部进行modCount++ */
hashmap_38_.size = 0;
hashmap_38_.init();
hashmap_38_.putAllForCreate(this);
return hashmap_38_; /最后返回此hashmap对象/
}
/*此方法在指定的地方添加一个新的对象,指定的地方为 i_40_*/
void addEntry(int i, Object object, Object object_39_, int i_40_) {
Entry entry = table[i_40_];
table[i_40_] = new Entry(i, object, object_39_, entry); /*这句代码将新加的对象加到table[i_40_]处*/
/*进行容量大小判定,如果因为多加一个对象而超出容量,则扩容*/
if (size++ >= threshold)
resize(2 * table.length);
}
/*原理同上*/
void createEntry(int i, Object object, Object object_41_, int i_42_) {
Entry entry = table[i_42_];
table[i_42_] = new Entry(i, object, object_41_, entry);
size++;
}
Iterator newKeyIterator() {
return new KeyIterator(null);
}
Iterator newValueIterator() {
return new ValueIterator(null);
}
Iterator newEntryIterator() {
return new EntryIterator(null);
}
public Set keySet() {
Set set = keySet;
return set != null ? set : (keySet = new KeySet(null));
}
public Collection values() {
Collection collection = values;
return collection != null ? collection : (values = new Values(null));
}
/*entrySet集合*/
public Set entrySet() {
return entrySet0();
}
private Set entrySet0() {
Set set = entrySet;
return set != null ? set : (entrySet = new EntrySet(null));
}
/*下面两个方法我几乎没用过,建议去百度看看其他大神的解释,我这就不多说了*/
private void writeObject(ObjectOutputStream objectoutputstream)
throws IOException {
Iterator iterator = size > 0 ? entrySet0().iterator() : null;
objectoutputstream.defaultWriteObject();
objectoutputstream.writeInt(table.length);
objectoutputstream.writeInt(size);
if (iterator != null) {
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
objectoutputstream.writeObject(entry.getKey());
objectoutputstream.writeObject(entry.getValue());
}
}
}
private void readObject(ObjectInputStream objectinputstream)
throws IOException, ClassNotFoundException {
objectinputstream.defaultReadObject();
int i = objectinputstream.readInt();
table = new Entry[i];
init();
int i_43_ = objectinputstream.readInt();
for (int i_44_ = 0; i_44_ < i_43_; i_44_++) {
Object object = objectinputstream.readObject();
Object object_45_ = objectinputstream.readObject();
putForCreate(object, object_45_);
}
}
int capacity() {
return table.length;
}
float loadFactor() {
return loadFactor;
}
}
HashSet源码及分析 因为hashset实际上就是hashmap的封装,所以它内容很少,基本很多方法都是直接用hashmap里的方法,不过只是hashset里面的value值是不重复的而已
/*
可以看到,hashset继承了AbstractSet接口,实现了Set,Cloneable, Serializable接口
*/
public class HashSet extends AbstractSet
implements Set, Cloneable, Serializable
{
/*
serialVersionUID序列id,
transient HashMap map 说一下transient 。transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。然而非transient型的变量是被包括进去的。我们也可以看到,Hashset里有以HashMap定义的map,可以说,HashSet实际上就是用HashMap来实现的
*/
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap map;
/*HashSet里的value就是PRESENT对象,*/
private static final Object PRESENT = new Object();
/*默认构造函数,创建出一个HashMap对象,以HashMap默认的16容量和0.75的负载因子创建*/
public HashSet() {
map = new HashMap();
}
/*传入collection集合对象来创建一个map对象,也是使用的是hashmap里的一个构造函数来创建map对象*/
public HashSet(Collection collection) {
map = new HashMap(Math.max(((int) ((float) collection.size() / 0.75F)
+ 1),
16));
addAll(collection);/*addall() hashmap里的静态方法*/
}
/*以下几个都是hashmap的构造函数,大家看看就知道什么意思了,后面的代码里会说*/
public HashSet(int i, float f) {
map = new HashMap(i, f);
}
public HashSet(int i) {
map = new HashMap(i);
}
HashSet(int i, float f, boolean bool) {
map = new LinkedHashMap(i, f);
}
/*Iterator迭代器,用来迭代出keySet里的值*/
public Iterator iterator() {
return map.keySet().iterator();
}
/*map的大小*/
public int size() {
return map.size();
}
/*判断是否为空*/
public boolean isEmpty() {
return map.isEmpty();
}
/*由于hashset里面只存value,所以contains方法里直接调用map里的containsKey()方法就行了,因为其实hashmap里的key集合就是一个hashset,key的值是不会重复的*/
public boolean contains(Object object) {
return map.containsKey(object);
}
/*add方法,调用map的put方法,上面hashmap里已经解释过了*/
public boolean add(Object object) {
return map.put(object, PRESENT) == null;
}
/*和hashmap的remove方法原理一样的*/
public boolean remove(Object object) {
return map.remove(object) == PRESENT;
}
/*和hashmap的clear的实现步骤是一样的*/
public void clear() {
map.clear();
}
/*基本上都是直接用的hashmap的clone方法*/
public Object clone() {
HashSet hashset_0_;
try {
HashSet hashset_1_ = (HashSet) super.clone();
hashset_1_.map = (HashMap) map.clone();
hashset_0_ = hashset_1_;
} catch (CloneNotSupportedException clonenotsupportedexception) {
throw new InternalError();
}
return hashset_0_;
}
private void writeObject(ObjectOutputStream objectoutputstream)
throws IOException {
objectoutputstream.defaultWriteObject();
objectoutputstream.writeInt(map.capacity());
objectoutputstream.writeFloat(map.loadFactor());
objectoutputstream.writeInt(map.size());
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext())
objectoutputstream.writeObject(iterator.next());
}
private void readObject(ObjectInputStream objectinputstream)
throws IOException, ClassNotFoundException {
objectinputstream.defaultReadObject();
int i = objectinputstream.readInt();
float f = objectinputstream.readFloat();
map = (this instanceof LinkedHashSet
? (HashMap) new LinkedHashMap(i, f) : new HashMap(i, f));
int i_2_ = objectinputstream.readInt();
for (int i_3_ = 0; i_3_ < i_2_; i_3_++) {
Object object = objectinputstream.readObject();
map.put(object, PRESENT);
}
}
}
分析完了hashmap和hashset的源码,我们来总结一下他们的遍历方式吧。
1:hashmap遍历的方式
第一种:
Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
}
效率高,以后一定要使用此种方式!
第二种:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Object key = iter.next();
Object val = map.get(key);
}
效率低,以后尽量少使用!
2:hashset的遍历方式
hashset遍历的方式很单一,就是直接使用迭代器来遍历
Set set = new HashSet(); //集合都可以用Iterator来遍历
Iterator it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
hashmap和hashset的源码和分析就到这里了,第一次写博客,可能有很多地方写的不好,要是有写的不对的地方,欢迎前来指正!谢谢!