一、equals()、==、compareTo()
equals()用于判断值,==用于判断比较内容和内存地址是否相等
”.equals()”点运算符只能用于类的成员或者方法,所以基本的数据类型(逻辑型boolean,字符型char,整型byte,short,int,long,浮点型float,double)都不能使用.equals进行判断,此时只能使用“==”进行判断,此时“==”的意义只是数字上的和字符上的相等。
compareTo() 方法用于将 Number 对象与方法的参数进行比较。可用于比较 Byte, Double, Integer, Float, Long 或 Short等。该方法用于两个相同数据类型的比较,两个不同类型的数据不能用此方法来比较。
二、例子
String sentence1 = "例句";
String sentence2 = "例句";
System.out.println(sentence1 == sentence2);//true
System.out.println(sentence1.equals(sentence2));//true
最为代表性的是String这个既不是基本的数据类型但是却非常频繁的被使用的这么一种数据结构,先对“==”进行测试;“==”和“.equals()”的情况一样其结果为true。其实这个时候我是很疑惑的,为什么他们的结果都是相同的呢?在java.lang.String的源码中,“.equals”方法是这样被定义的:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;//如果调用.equals()方法中的参数是本身,则返回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;
}
所以可以从源码中看到,实际上.equals是在进行值的分析(一个一个char进行比较)。而我推测“==”是专门用于内容和内存地址的比较。我用了下面的代码进行证明
String sentence1 = new String("a");
String sentence2 = new String("a");
System.out.println(sentence1 == sentence2);//false
System.out.println(sentence1.equals(sentence2));//true
sentence1 = sentence2;//此时让两个例句的地址相等
System.out.println(sentence1 == sentence2);//true
三、compareTo()和compare()方法的比较
方法的比较
1.compareTo(Object obj)方法是java.lang.Comparable接口中的方法, 当需要对类的对象进行排序时,该类需要实Comparable接口,必须重写public int compareTo(T)方法,
String类等一些类默认实现了该接口;
String类默认实现了该接口 compareTo()方法的返回值 s1.compareTo(s2)—》s1 与 s2 的ASC码 的差值,其实就是字典排序;
2.compare(Object o1, Object o2)方法是java.util.Comparator接口的方法, 它实际上用的是待比较对象的compareTo(Object obj)方法;
3.arrayList排序时
1.Collections.sort(list) 会自动调用User实现的Comparable的compareTo()方法
Comparator comparator = new Comparator() {
@Override
public int compare(User user0, User user1) {
return user0.id.compareTo(user1.id);
}
};
Collections.sort(list, comparator)//也可以重新实现排序的方法
四、float型和double类型的相等判断
float型和double型是JAVA的基本类型,用于浮点数表示,在JAVA中float型占4个字节32位,double型占8个字节64位,一般比较适合用于工程测量计算中,其在内存里的存储结构如下:
float型:
符号位(1 bit)
指数(8 bit)
尾数(23 bit)
double型:
符号位(1 bit)
指数(11 bit)
尾数(52 bit)
注意:从左到右是从低位到高位,而在计算机内部是采用逆序存储的。
JAVA中float型和double型是不能被计算机精确存储的。以double类型数据1.10举例计算机如何将浮点型数据转换成二进制存储:
整数部分:1,转换成二进制1
小数部分:0.1
0.1*2=0.2取整数部分0,基数=0.2
0.2*2=0.4取整数部分0,基数=0.4
0.4*2=0.8取整数部分0,基数=0.8
0.8*2=1.6取整数部分1,基数=1.6-1=0.6
0.6*2=1.2取整数部分1,基数=1.2-1=0.2
0.2*2=0.4取整数部分0,基数=0.4
···
直至基数为0。
1.1用二进制表示为:1.000110……,即0.1 = 0*2^(-1)+0*2^(-2)+0*2^(-3)+1*2^(-4)+……而double型的小数部分只有52位,当向后计算 52位后基数还不为0时,后面的部分只能舍弃,从这里可以看出float型、double型并不能准确表示每一位小数。
因此。程序中应尽量避免浮点数的比较。在循环中,检测两个浮点数是否相等需要格外小心,如下的for循环可能永远不会结束:
for(double i = 0; i != 10; i += 0.1);
浮点数能表示的精度是有限的,在计算过程中不可避免的会出现截尾而损失精度,所以如果要判断一个浮点数double_x是否等于0,用double_x == 0这样的判断是不合适的,如果double_x是一系列计算的结果或者是外部传感器的输入值,那么它几乎不可能是0,它大概率是一个接近0的小数,比如0.000002,
比较double数据是否相等的方法
方法一:若精度要求不高,比如因为传感器有误差,小于0.001的数都可以认为等于0,那么就定义epsilon = 0.001:
final double epsilon = 0.001;
double double_x = 0.0;
if(Math.abs(double_x - 0) < epsilon)
{
System.out.println("true");
}
方法二:转换成字符串之后用equals方法比较
如果要比较的两个double数据的字符串精度相等,可以将数据转换成String然后借助String的equals方法来间接实现比较两个double数据是否相等。
Double.toString(double_x).equals(Double.toString(double_y))
注意:这种方法只适用于比较精度相同的数据,并且是只用用于比较是否相等的情况下,不能用来判断大小。
方法三:转换成Long之后用==方法比较
使用Sun提供的Double.doubleToLongBits()方法,该方法可以将double转换成long型数据,从而可以使double按照long的方法(<, >, ==)判断是否大小和是否相等。
Double.doubleToLongBits(0.01) == Double.doubleToLongBits(0.01)
Double.doubleToLongBits(0.02) > Double.doubleToLongBits(0.01)
Double.doubleToLongBits(0.02) < Double.doubleToLongBits(0.01)
方法四:使用BigDecimal类型的equals方法或compareTo方法
使用字符串形式的float型和double型构造BigDecimal:BigDecimal(String val)。BigDecimal的euquals方法是先判断要比较的数据类型,如果对象类型一致前提下同时判断精确度(scale)和值是否一致;compareTo方法则不会比较精确度,把精确度低的那个对象转换为高精确度,只比较数值的大小。
System.out.println(new BigDecimal("1.2").equals(new BigDecimal("1.20"))); //输出false
System.out.println(new BigDecimal("1.2").compareTo(new BigDecimal("1.20")) == 0); //输出true
System.out.println(new BigDecimal(1.2).equals(new BigDecimal("1.20"))); //输出false
System.out.println(new BigDecimal(1.2).compareTo(new BigDecimal("1.20")) == 0); //输出false
System.out.println(new BigDecimal(1.2).equals(new BigDecimal(1.20))); //输出true
System.out.println(new BigDecimal(1.2).compareTo(new BigDecimal(1.20)) == 0);//输出true