【JavaSE】Java中的数据比较-创新互联
在Java中数据类型主要分为两类:基本数据类型和引用数据类型。
创新互联建站专注于揭东企业网站建设,响应式网站开发,商城开发。揭东网站建设公司,为揭东等地区提供建站服务。全流程按需定制开发,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务1.基本数据类型如何比较?
2.基本数据类型和引用类型如何比较?
3.引用类型间如何比较?
文章目录- Java中的数据比较
- 1. 基本数据类型间如何比较?
- 2. 基本数据类型和引用类型(包装类)如何比较?
- 2.1 小结
- 3. 引用类型间如何比较?
- 3.1 包装类间的比较
- 3.1.1 小结
- 3.1.2 实践
- 3.2 自定义引用类型的比较
- 3.2.1 equals方法
- 3.2.2 compareTo方法
- 3.2.3 compare方法
- 3.2.4 compareTo() 和 compare()
基本数据类型又细化为整型、字符型、浮点型和布尔型;
基本数据类型间通过关系运算符就可以直接比较,对数值比较。
不同的基本数据类型能不能比较?
不是任意之间都能比较。基本数据类型间,除了布尔型不可以与其他类型比较,只能自己和自己比较。整型、字符型、浮点型可以相互比较(可以比较,但是比如字符和浮点比较有什么意义?合法但不合理),不同类型的比较会发生类型提升,数据类型小的会被提升到数据类型大的。字符型采用的是Unicode编码,本质还是整型。
特别注意浮点型比较会存在精度问题。浮点型的计算或者类型提升都会出现精度问题。
System.out.println(0.1f == 0.1); // false
详细参考:author:平白 – 浮点数比较
2. 基本数据类型和引用类型(包装类)如何比较?
这里主要针对整型基本数据类型和其包装类的比较。
比较之前,问为什么有基本数据类型和包装类?
解释传送门 – 基本数据类型和包装类
Integer a = 100; // 自动装箱
Long b = 100L;// 自动装箱
System.out.println(a == 100);//1. true
System.out.println(b == 100);//2. true
System.out.println(a.equals(100));//3. true
System.out.println(a.compareTo(100));//4. true
System.out.println(a.equals(b));//5. false
基本数据类型与包装类直接==比较时,包装类会先拆箱,然后与基本数据类型比较,比较规则和基本数据类型之间的比较规则一样。(解释1、2)
包装类都已经重写了equals和compareTo方法,使用这样的方法直接和基本数据类型比较时,先将基本类型装箱然后传参,在equals方法内会先进行类型判断进而拆箱比较,compareTo方法也是的相同类型然后拿到包装类的值在进行数值比较。(解释3、4)
// Integer equals方法和compareTo方法源码
public boolean equals(Object obj) {if (obj instanceof Integer) {// 类型检查
return value == ((Integer)obj).intValue();
}
return false;
}
public int compareTo(Integer anotherInteger) {// 类型检查
return compare(this.value, anotherInteger.value);
}
public static int compare(int x, int y) {return (x< y) ? -1 : ((x == y) ? 0 : 1);
}
2.1 小结基本数据类型和包装类比较直接使用运算符比较即可,因为包装类会自动拆箱,最终还是基本数据类型间的比较。
注意到上述基本数据类型和包装类的代码第七行,是包装类和包装类的比较,结果为false,那通过上面equals的代码可以看到,比较前会进行类型检查(检查是不是Integer或者其子类),b是Long类型,所以为false。
那包装类能否使用运算符比较?也即引用类型能否使用运算符比较?
3. 引用类型间如何比较? 3.1 包装类间的比较
public static void main(String[] args) {Integer a = 6;
Integer b = 6;
Integer c = new Integer(6);
Integer d = new Integer(6);
Integer f = 128;
Integer g = 128;
Long l = 6L;
System.out.println(a == b); //1. true
System.out.println(a.equals(b));//2. true
System.out.println(a == c);//3. true
System.out.println(c == d);//4. false
System.out.println(c.equals(d));//5. true
System.out.println(a == l);//6. 编译器红波浪警告--cannot be applied to 'java.lang.Integer', 'java.lang.Long'
System.out.println(a.equals(l));//7. false
System.out.println(f == g);//8. false
}
3.1.1 小结
- 首先引用类型间使用==比较的是地址!!!
- Integer类内有一个对象缓存区,缓存范围为-128到127,当该范围内的数据装箱时,会直接从对象缓冲区引用对象。 范围之外的数据装箱时会直接在堆区实例化Integer对象,相当于new Integer(x)。(解释行1,3,4,8)
- 引用类型使用==比较时两边的类型要一样。(解释行6)
- equals方法内会先进行类型判断进而拆箱比较,根据源码不是一个类型则直接返回false。(解释5,7)
- 基本数据类型包装类中的Byte、Short、Integer、Long的高频缓存范围为-128到127;Character的高频缓存为-128到127;Float、Double没有高频缓存区。
3.1.2 实践1、基本数据类型使用==比较的是数值;
2、引用类型间使用==比较的是地址;
3、包装类之间比较最好使用equals和compareTo方法,避免因为缓冲区而出现问题,且用着两个方法时要注意类型问题。
单独谈论这些问题可能体会不深,一下两个练习题可以加深理解。
- 栈的压入、弹出序列
- 155. 最小栈 - 力扣(LeetCode)
3.2 自定义引用类型的比较
3.2.1 equals方法
- 像包装类这种是java提供的实现类以及String类等,内部都重写了equals和compareTo方法,那如果是自定义的类如何比较?既然java内部提供的类可以重写这些方法,那自定义类是不是也可以?
- Java里面除了Object类,所有的类都是默认会继承Object父类。Object类中就提供了equals方法。既然所有的类都继承了Object类,为什么要重写equals?
- 查看Object类equals方法:
public boolean equals(Object obj) {return (this == obj);
}
- Object类中的equals方法最终还是==比较,也即比较地址。这不满足其他类的需求所以被重写。
- equals方法只能判断相等不相等!
Integer的equals方法:
public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();
}
return false;
}
自定义引用类型equals方法:
- 继承equals方法
class Student {int id;
int name;
public Student(int id, int name) {this.id = id;
this.name = name;
}
}
public class Test {public static void main(String[] args) {Student student1 = new Student(1,"apple");
Student student2 = new Student(1,"apple");
System.out.println(student1.equals(student2)); // false
}
}
因为继承Object类的equals方法所以还是比较地址。
- 重写equals方法
class Student {int id;
String name;
public Student(int id, String name) {this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id && Objects.equals(name, student.name);
}
@Override
public int hashCode() {return Objects.hash(id, name);
}
}
public class Test {public static void main(String[] args) {Student student1 = new Student(1,"apple");
Student student2 = new Student(1,"apple");
System.out.println(student1.equals(student2)); // true
}
}
注意重写equals方法一般都要重写hashCode方法!!!
参考 – author:[多动手,勤思考]–为什么重写equals后需要重写hashCode
3.2.2 compareTo方法泛型的比较接口类Comparable提供了compareTo抽象方法。
使用流程:实现Comparable接口重写compareTo方法
class Student implements Comparable{int id;
String name;
public Student(int id, String name) {this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id && Objects.equals(name, student.name);
}
@Override
public int hashCode() {return Objects.hash(id, name);com
}
@Override
public int compareTo(Student o) {return this.id - o.id;
}
}
public class Test {public static void main(String[] args) {Student student1 = new Student(1,"apple");
Student student2 = new Student(1,"apple");
System.out.println(student1.compareTo(student2)); // 0
}
}
注意事项:
implements Comparable
– 括号内指明比较的对象。 public int compareTo(Student o) – 谁调用compareTo方法谁是this。
3.2.3 compare方法
泛型的比较接口类Comparator提供了compare抽象方法。
使用流程:子类继承Comparator重写compare方法。
sample 1:
class stuIdComparator implements Comparator{@Override
public int compare(Student o1, Student o2) {return o1.id - o2.id;
}
}
public class Test {public static void main(String[] args) {Student student1 = new Student(1,"apple");
Student student2 = new Student(1,"apple");
System.out.println(comparator.compare(student1, student2)); // 0
}
}
sample 2:
class stuIdComparator implements Comparator{@Override
public int compare(Student o1, Student o2) {return o2.id - o1.id;// !!!
}
}
class Student {int id;
String name;
public Student(int id, String name) {this.id = id;
this.name = name;
}
@Override
public String toString() {return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class Test {public static void main(String[] args) {Student student1 = new Student(1, "apple");
Student student2 = new Student(2, "apple");
Student[] students = new Student[]{student1,student2};
stuIdComparator comparator = new stuIdComparator();
Arrays.sort(students,comparator);// 传入比较器
System.out.println(Arrays.toString(students));
}
}
stdout:
[Student{id=2, name='apple'}, Student{id=1, name='apple'}]
3.2.4 compareTo() 和 compare()何为侵入性? – 指代码产生对框架的依赖,离不开框架了。这里框架等价于这两个方法。
compareTo()对类的侵入性强。(翻译翻译)类一旦实现Comparable 接口必须重写该方法,而且如果改变比较的属性则要改变方法,那么调用改方法的对象可能也要做出相应的调整,所以说该方法对类的比较影响较大。
compare()对算法代码实现侵入性强。 该比较器可以根据需求去比较类中的属性,可以定义多个比较器,但是代码使用该方法则需实例化一个比较器。
一句话前者直接作用于类中,后者作用于类外。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
网页名称:【JavaSE】Java中的数据比较-创新互联
网站URL:http://pwwzsj.com/article/dhsjgh.html