## Java专题二:相等与比较
[TOC]
### 2.1.运算符==
基本数据类型(byte、short、int、long、char、float、double、boolean):判断数值是否相等
引用数据类型(类的对象):判断对象的地址是否相等,一般通过new关键词创建的对象都是不相等的。
### 2.2.equals方法
**equals方法是判断对象相等最常使用的方法。**
如:
在ArrayList中判断是否包含某元素contains方法:
1.判断是否待查找的对象是否为null,为null的话,进入第2步,否则进入第3步
2.遍历ArrayList的元素数组,查找是否数组中包含null,查找结束
3.遍历ArrayList的元素数组,调用每个元素的equals方法,判断是否相等
**说明:**
如果2个对象的equals方法相等,则它们的hashCode方法一定会要产生相同的整形值,所以在定义类重载equals时候最好重写hashCode方法。
**定义equals方法一般原则**:
1. 判断this对象与anObject对象是否相等(`this == anObject`)
2. 判断anObject对象是否为类或其子类对象(`anObject instanceof String`)
3. 比较类中属性是否相等
基本类型,直接使用==判断
集合数组类型,遍历集合数组使用相应equals方法判断
引用数据类型,使用相应equals方法判断
4. 重写equals方法是总要重写hashCode方法(Always override hashCode when you override equals)
如String类的equals方法:
```java
// java.lang.String#equals
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
```
### 2.3.hashCode方法
如:
HashMap的Hash表结构中,使用哈希函数定位元素的位置就是通过元素的hash值,即(h = key.hashCode()) ^ (h >>> 16);因此如果2个对象的hashCode返回相同的值,意味着产生冲突或者是同一个元素(Key的equals方法相等)
**定义hashCode方法一般原则**:
1. 定义int类型变量hashCode并赋值1(`int hashCode = 1;`)
2. 对于每个成员变量,进行如下计算hash code `c`(根据字段类型):
boolean: ` (f ? 1 : 0)`
byte, char, short, int: `(int) f`
long: `(int) (f ^ (f >>> 32))`
float: `Float.floatToIntBits(f)`
double: `Double.doubleToLongBits(f)`
Object: `(obj==null ? 0 : obj.hashCode())`
3. 对每个字段进行如下操作: `hashCode = 31 * hashCode + c;`
4. 返回hashCode(`return hashCode;`)
```java
//java.util.AbstractList#hashCode
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
```
### 2.4.Comparable接口与Comparator接口
涉及数组或列表有序存储或排序问题,如TreeMap自动排序和Arrays.sort方法,public static <T> void sort(T[] a, Comparator<? super T> c),都需要比较大小。
```java
public interface Comparable<T> {
public int compareTo(T o);
}
```
```java
public interface Comparator<T> {
int compare(T o1, T o2);
}
```
在使用TreeMap时会对插入键值对元素的Key进行排序,必须通过比较排序。而比较就要用到上面2个接口:
**第1种** :在TreeMap构造方法`public TreeMap(Comparator<? super K> comparator)`直接指定一个比较器,操作元素时调用比较器的compare方法实现Key的大小比较;
**第2种** :Key类实现Comparable接口,操作元素时调用Key的compare方法来实现大小的比较。
其它则如下面所示,会抛出异常。
```java
class A{
}
public class TreeMapTest {
public static void main(String[] args){
TreeMap map = new TreeMap<A, String>();
map.put(new A(), "null");;
}
}
```
**运行报异常:** Exception in thread "main" java.lang.ClassCastException: A cannot be cast to java.lang.Comparable
- JavaCook
- Java专题零:类的继承
- Java专题一:数据类型
- Java专题二:相等与比较
- Java专题三:集合
- Java专题四:异常
- Java专题五:遍历与迭代
- Java专题六:运算符
- Java专题七:正则表达式
- Java专题八:泛型
- Java专题九:反射
- Java专题九(1):反射
- Java专题九(2):动态代理
- Java专题十:日期与时间
- Java专题十一:IO与NIO
- Java专题十一(1):IO
- Java专题十一(2):NIO
- Java专题十二:网络
- Java专题十三:并发编程
- Java专题十三(1):线程与线程池
- Java专题十三(2):线程安全与同步
- Java专题十三(3):内存模型、volatile、ThreadLocal
- Java专题十四:JDBC
- Java专题十五:日志
- Java专题十六:定时任务
- Java专题十七:JavaMail
- Java专题十八:注解
- Java专题十九:浅拷贝与深拷贝
- Java专题二十:设计模式
- Java专题二十一:序列化与反序列化
- 附加专题一:MySQL
- MySQL专题零:简介
- MySQL专题一:安装与连接
- MySQL专题二:DDL与DML语法
- MySQL专题三:工作原理
- MySQL专题四:InnoDB存储引擎
- MySQL专题五:sql优化
- MySQL专题六:数据类型
- 附加专题二:Mybatis
- Mybatis专题零:简介
- Mybatis专题一:配置文件
- Mybatis专题二:映射文件
- Mybatis专题三:动态SQL
- Mybatis专题四:源码解析
- 附加专题三:Web编程
- Web专题零:HTTP协议
- Web专题一:Servlet
- Web专题二:Cookie与Session
- 附加专题四:Redis
- Redis专题一:数据类型
- Redis专题二:事务
- Redis专题三:key的过期
- Redis专题四:消息队列
- Redis专题五:持久化