Java开发者必备:深入理解元素与对象比较的底层原理

Java开发者必备:深入理解元素与对象比较的底层原理

个人主页:顾漂亮
文章专栏:Java数据结构

1.元素的比较

  • Java中,基本类型的对象可以直接比较大小
  • 基本类型有:四类八种
    • 四类:整型、浮点型、字符型、布尔型
    • 八种:
数据类型 关键字 内存占用 范围
字节型 byte 1字节 -128 ~ 127(-2^7 ~ 2^7-1)
短整型 short 2字节 -32768 ~ 32767(-2^15 ~ 2^15-1)
整形 int 4字节 -2^31 ~ 2^31-1
长整型 long 8字节 -2^63 ~ 2^63-1
单精度浮点数 float 4字节 有范围,一般不关注
双精度浮点数 double 8字节 有范围,一般不关注
字符型 char 2字节 0 ~ 65535
布尔型 boolean 没有明确规定 true or false
public static void main(String[] args) {
    int a = 10;
    int b = 20;
    System.out.println(a > b);//false
    System.out.println(a < b);//true
    System.out.println(a == b);//false
    char c1 = 'A';
    char c2 = 'B';
    System.out.println(c1 > c2);//false
    System.out.println(c1 < c2);//true
    System.out.println(c1 == c2);//false
    boolean b1 = true;
    boolean b2 = false;
    System.out.println(b1 == b2);//false
    System.out.println(b1 != b2);//true
}

**注意:**Java中引用类型的变量不能直接按照> 或者 < 方式进行比较,但是可以用 == 比较。因为,对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equals方法,而默认情况下调用的就是equals方法但是该方法没有比较引用类型变量的内容,而是直接比较引用类型变量的地址。

//直接比较两个引用对象的地址
public boolean equals(Object obj) {
    return (this == obj);
}

2.对象的比较

2.1覆写equals

//自定义类型Card
public class Card {
    public int rank;//数值
    public String suit;//花色

    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }

    @Override
    public boolean equals(Object o) {
        //自己和o比较
        if (this == o)
            return true;
        //如果 o == null 或者 传入的对象类型不是Card
        if (o == null || getClass() != o.getClass())
            return false;
        //注意,基本类型可以直接比较,但是引用类型最好调用其equals方法
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }
}

**注意:**该方法只能比较两个对象是否相等,不能按照大于或者小于方式进行比较

2.2基于Comparable接口类的比较

public class Card implements Comparable<Card>{
    public int rank;//数值
    public String suit;//花色

    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    @Override
    public int compareTo(Card o) {
        if(o == null){
            return 1;
        }
        //基于数值比较
        return rank - o.rank;
    }
}

Comparable是Java.lang中的接口类,可以直接使用

2.3基于比较器比较

public class Card {
    public int rank;//数值
    public String suit;//花色

    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}
//自定义一个比较器对象
class CardComparator implements Comparator{
    @Override
    public int compare(Card o1, Card o2) {
        if(o1 == null && o2 == null){
            return 0;
        }
        if(o1 == null){
            return -1;
        }
        if(o2 == null){
            return 1;
        }
        //基于数值比较
        return o1.rank -o2.rank;
    }
}
//测试
public static void main(String[] args) {
    Card card1 = new Card(5, "梅花");
    Card card2 = new Card(6, "梅花");
    CardComparator comparator = new CardComparator();
    System.out.println(comparator.compare(card1, card2));//-1
}

3.3三种方式比较

覆写的方法 说明
Object.equals 因为所有类都是继承自Object的,所以直接覆写即可,不过只能比较相等与否
Comparable.compareTo 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序
Comparator.compare 需要实现一个比较器对象,对待比较类的侵入性较弱,但对算法代码实现侵入性强

3.使用PriorityQueue

3.1PriorityQueue中插入对象

  • 优先级队列在插入元素时有个要求:插入的元素不能是null或者元素之间必须可以比较
  • 如果是基本类型,可以直接插入堆中,如果是引用类型,必须实现上述的三种方法来进行对象的比较

3.2使用PriorityQueue创建大小堆,解决TOPK问题

import java.util.Comparator;
import java.util.Iterator;
import java.util.PriorityQueue;

//使用比较器创建大根堆
class Greater implements Comparator<Integer>{
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2-o1;
    }
}
public class TOPK {
    public int[] getMin(int[] array, int k){
        if(array == null){
            return null;
        }
        if(k <= 0){
            return new int[0];
        }
        Greater greater = new Greater();
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(greater);
        //将前k个元素放入大堆中
        for (int i = 0; i < k; i++) {
            priorityQueue.offer(array[i]);
        }

        //将剩下元素与堆中元素进行比较
        for (int i = k; i < array.length; i++) {
            int top = priorityQueue.peek();
            if(top > array[i]){
                priorityQueue.poll();
                priorityQueue.offer(array[i]);
            }
        }
        int[] smallest = new int[k];
        //取除堆中元素 -- 迭代器遍历元素
        Iterator<Integer> iterator = priorityQueue.iterator();
        int i = 0;
        while(iterator.hasNext()){
            smallest[i] = iterator.next();
            i++;
        }
        return smallest;
    }
}




public static void main(String[] args) {
    TOPK topk = new TOPK();
    int[] array = {4,1,9,2,8,0,7,3,6,5};
    System.out.println(Arrays.toString(topk.getMin(array, 3)));// [2 1 0]
}

你可能感兴趣的:(Java数据结构,java,算法,开发语言,数据结构)