一、 equals与==
==
对于基本数据类型(int, float, double, short, long, boolean, char, byte
),==
比较的是他们的值,而对于引用类型,返回的使他们引用的比较(也就是地址的比较);
equals
equals()是Object类下的一个方法,默认其内部实现就是通过==
实现的。
public boolean equals(Object obj) {
return (this == obj);
}
二者区别
-
equals()
只能对对象使用,如果对象为null将会空指针异常,而==
既可以对基本数据类型使用也可以对引用类型使用,在对引用类型使用时,equals()
等价于==
; -
equals()
大部分场景下会被重写,重写成对于值得比较,比如String重写的equals()
方法;
public boolean equals(Object anObject) {
if (this == anObject) {//参数是否为这个对象的引用
return true;
}
if (anObject instanceof String) {//参数是否为正确的类型
String anotherString = (String)anObject;
//获取关键域,判断关键域是否匹配
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
二、hashCode()
引入
Java中的集合主要分为两类:List
和Set
,其中List表示有序集合,因为有序(这里的有序并不单指数组,包括链表,队列都可看做是有序的集合,有序是元素插入、删除有先后顺序),所以集合元素可以重复;而Set
本身是无序集合(如HashMap, HashSet, HashTable),元素不允许出现重复。
那么Set
如何判断一个元素是否在集合中已经存在呢,当然我们可以遍历整个集合,但这样每次添加一个元素都对整个集合进行一次遍历,效率非常低。这里我们引入hashCode()
。
定义
hashCode()
的作用就是返回一个hash码(int),这个hash码作为对象散列的key输入,我们需要尽可能保证每个对象的hash码不同,以便对对象进行区分,实际上Java确实能保证这点,它是通过对对象的地址进行一定的运算生成对象的hash码。
作用
无序集合内部通常会对所有元素的hash码进行保存,以HashMap
为例,其内部存在一个table用以保存所有元素的hash码,当需要往无序集合(如HashMap
)中添加一个新的对象时,首先调用这个对象的hashCode()
方法获取其hash码,如果在table中找不到此对象的hash码,则直接添加,如果能找到,则调用equals()
方法比较两个对象是否相同,如果相同就不进行保存,如果不同就重新hash,散列到另一个地址。这样等于是存在一个冲突处理,大大降低了equals()调用频率,进而显著提高了往无序集合中添加元素的效率。
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
这是HashMap中put的实现。