目录
一、基本类型的比较
Java中的基本类型的对象可以直接比较大小
public static void main(String[] args){
int a=1;
int b=2;
System.out.println(a>b); //false
double a1=1.1;
double b1=1.2;
System.out.println(a1<b1); //true
char c='a';
char d='b';
System.out.println(c>d); //flase
boolean e=false;
boolean f=true;
System.out.println(e==f); //false
}
二、对象的比较
1、定义
Java中引用类型的变量不能直接按照“>”或“<”方式进行比较。但是可以用“==”进行比较,因为对于用户实现自定义类型,都是默认继承自Object类,Object类中提供了equal方法,而“==”默认情况下调用的就是equal方法。该方法的比较规则是没有比较引用变量引用对象的内容,而是直接比较引用变量的地址,因此很多时候不适用。
public boolean equals(Object obj){
return (this==obj);
//直接比较两个引用变量的地址
}
2、方法
(1).覆写基类的equals
public class dog{
public int age;
public String name;
public dog(int age,String name){
this.age=age;
this.name=name;
}
@Override
public boolean equals(Object o){
//与自身相比较,如果指向同一个对象,返回true
if(this==o){
return true;
}
if(o==null||!(o instanceof dog)){
//如果传入的为null,或者o不是dog的子类,返回false
return false;
}
dog d=(dog)o;
//只要类中的两个对象都相等,就认为两个类相等
return age==d.age&&name.equals(d.name);
}
}
注:覆写基类equal的方式虽然可以比较,但缺陷是equal只能按照相等进行比较,不能按照大于或小于的方式进行比较 。
(2).基于Comparable接口类的比较
Comparable是JDK提供的泛型的比较接口类。
public interface Comparable<E>{
int compareTo(E o);
//<0:表示this指向的对象小于o指向的对象
//==0:表示this指向的对象等于o指向的对象
//>0:表示this指向的对象大于o指向的对象
}
注:Comparable是java.lang中的接口类,可以直接使用,不需要导包
对于用户自定义类型,如果想要按照大小与方式进行比较时。在定义类时,实现Comparable接口即可,然后在类中重写compareTo方法。
public class dog implements Comparable<dog>{
public int age;
public String name;
public dog(int age,String name){
this.age=age;
this.name=name;
}
@Override
public int compareTo(dog d){
if(o==null){
return 1;
}
return age-d.age;
}
public static void main(String[] args){
dog d1=new dog(10,"二哈");
dog d2=new dog(12,"二哈");
dog d3=new dog(10,"二哈")
System.out.println(d1.compareTo(d3)); //==0,表示相等
System.out.println(d1.compareTo(d2)); //<0,表示d1比较小
System.out.println(d2.compareTo(d1)); //>0,表示d2比较大
}
}
(3).基于比较器的比较
用户自定义比较器类,实现Comparator接口
public interface Comparator<T>{
int compare(T o1,T o2);
//<0:表示o1指向的对象小于o2指向的对象
//==0:表示o1指向的对象等于o2指向的对象
//>0:表示o1指向的对象大于o2指向的对象
}
注:Comparator是java.util包中的泛型接口类,使用前需要导包
覆写Comparator中的compare方法
import java.util.Comparator;
class dog{
public int age;
public String name;
public dog(int age,String name){
this.age=age;
this.name=name;
}
}
class dogComparator implements Comparator<dog>{
@Override
public int compare(dog d1,dog d2){
if(d1==d2){
return 0;
}
if(o1==null){
return -1;
}
if(o2==null){
return 1;
}
return d1.age-d2.age;
}
public static void main(String[] args){
dog d1=new dog(10,"二哈");
dog d2=new dog(12,"二哈");
dog d3=new dog(10,"二哈");
//定义比较器对象
dogComparator c=new dogComparator();
//使用比较器对象进行比较
System.out.println(c.compare(d1,d3)); //==0,表示牌相等
System.out.println(c.compare(d1,d2)); //<0,表示d1比较小
System.out.println(c.compare(d2,d1)); //>0,表示d2比较大
}
}
3、对比
Object.equals | 因为所有类都是继承自Object的,所以直接覆写即可,不过只能比较相等与否 |
Comparable.compareTo | 需要手动实现接口,侵入性较强,但一旦实现,每次用该类都有顺序,属于内部顺序 |
Comparator.compare | 需要实现一个比较器对象,对待比较类的侵入性弱,但对于算法代码实现侵入性强 |
三、集合框架中的PriorityQueue的比较方式
集合框架中的PriorityQueue底层使用堆结构,因此其内部的元素必须能够比大小,PriorityQueue采用了Comparable和Comparator两种方式
- Comparable是默认的内部比较方式,如果用户插入自定义类型对象时,该类对象必须要实现Comparable接口,并覆写compareTo方法
- 用户使用比较器对象时,如果用户插入自定义类型对象时,必须要提供一个比较器类,让该类实现Comparator接口并覆写compare方法
四、应用——解决Topk问题
1、PriorityQueue创建大根堆和小根堆
(1).使用比较器创建小根堆
class cmp1 implements Comparator<Integer>{
@Overrider
public int compare(Integer o1,Integer o2){
return o1-o2;
}
}
(2).使用比较器创建大根堆
class cmp2 implements Comparator<Integer>{
@Overrider
public int compare(Integer o1,Integer o2){
return o2-o1;
}
}
2、代码
public class test{
public static int[] func(int[] array,int k){
if(k<=0){
return new int[k];
}
cmp2 c=new cmp2();
PriorityQueue<Integer> maxHeap=new PriorityQueue<>(c);
for(int i=0;i<k;i++){
maxHeap.offer(array[i]);
}
for(int i=k;i<array.length;i++){
int top=maxHeap.peek();
if(array[i]<top){
maxHeap.poll();
maxHeap.offer(array[i]);
}
}
int[] ret=new int[k];
for(int i=0;i<k;i++){
int val=maxHeap.poll();
ret[i]=val;
}
return ret;
}
}