Java~对象的比较(== VS equals)认识Comparable与Comparator和差异

比较相等

  1. :比较的是对象的身份(引用中存的地址是不是相同==)
  2. equals:默认也是调用 == 来比较身份,可以手动重写equals方法按自定义规则进行比较

PS
在自定义equals方法时必须注意

  1. 判断obj是否为null
  2. 判断obj是否与this为同一对象
  3. 判断obj是否可以强制转换
  4. 对obj进行强制转换,写自定义规则

实现

class Card implements Comparable<Card> {
    //定义一个牌的数据结构
    public String rank;
    public String shit;

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

    @Override
    public boolean equals(Object obj) {
        //第一步判断obj是否为空
        if(obj == null) {
            return false;
        }
        //第二步判断obj与this是否引用同一个对象
        if(obj == this) {
            return true;
        }
        //第三步判断obj是否可以强转为this类型
        if(!(obj instanceof Card)) {
            return false;
        }
        //第四步将obj强转为this类型,自定义判断相等
        Card o = (Card) obj;
        //按照数字大小进行比较
        int thisRank = rankToInt(this.rank);
        int oRank = rankToInt(o.rank);
        return thisRank == oRank;
    }

    public int rankToInt(String rank) {
        //将面值转为int型
        if("A".equals(rank)) {
            return 1;
        }
        if("J".equals(rank)) {
            return 11;
        }
        if("Q".equals(rank)) {
            return 12;
        }
        if("K".equals(rank)) {
            return 13;
        }
        return Integer.parseInt(rank);
    }

这样当我们进行== 与equals 判断相等的时候就会发生改变:

        Card card = new Card("10", "♥");
        Card card1 = new Card("A","♠");
        Card card4 = new Card("A", "♣");
        //直接等号比较
        System.out.println(card == card4);
        //
        Card card3 = card;
        System.out.println(card == card3);
        //进行equals比较,
        System.out.println(card.equals(card1));
        System.out.println(card.equals(card3));
        
 System.out.println(card1.equals(card4));

结果

false
true
false
true
true

认识认识Comparable

代码格式

public interface Comparable<E> { 
    // 返回值: 
    // < 0: 表示 this 指向的对象小于 o 指向的对象 
    // == 0: 表示 this 指向的对象等于 o 指向的对象 
    // > 0: 表示 this 指向的对象等于 o 指向的对象 
    int compareTo(E o);
 }

实例

class Card implements Comparable<Card> {
    //定义一个牌的数据结构
    public String rank;
    public String shit;

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

    @Override
    public boolean equals(Object obj) {
        //第一步判断obj是否为空
        if(obj == null) {
            return false;
        }
        //第二步判断obj与this是否引用同一个对象
        if(obj == this) {
            return true;
        }
        //第三步判断obj是否可以强转为this类型
        if(!(obj instanceof Card)) {
            return false;
        }
        //第四步将obj强转为this类型,自定义判断相等
        Card o = (Card) obj;
        //按照数字大小进行比较
        int thisRank = rankToInt(this.rank);
        int oRank = rankToInt(o.rank);
        return thisRank == oRank;
    }

    public int rankToInt(String rank) {
        //将面值转为int型
        if("A".equals(rank)) {
            return 1;
        }
        if("J".equals(rank)) {
            return 11;
        }
        if("Q".equals(rank)) {
            return 12;
        }
        if("K".equals(rank)) {
            return 13;
        }
        return Integer.parseInt(rank);
    }

    @Override
    public int compareTo(Card o) {
        //将this与o的面值进行转换成int型,然后进行比较
        int thisRank = rankToInt(this.rank);
        int oRank = rankToInt(o.rank);
        //如果要升序就是thisRank - oRank,降序就是反之
        return thisRank - oRank;
    }

    @Override
    public String toString() {
        return "Card{" +
                "rank='" + rank + '\'' +
                ", shit='" + shit + '\'' +
                '}';
    }
}

测试

        Card card = new Card("10", "♥");
        Card card1 = new Card("A","♠");
        Card card2 = new Card("K", "♣");
        Card card4 = new Card("A", "♣");
        List<Card> list = new ArrayList<>();
        list.add(card);
        list.add(card1);
        list.add(card2);
        list.add(card4);
        //集合类的排序方法
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);

结果

[Card{rank='10', shit='♥'}, Card{rank='A', shit='♠'}, Card{rank='K', shit='♣'}, Card{rank='A', shit='♣'}]
[Card{rank='A', shit='♠'}, Card{rank='A', shit='♣'}, Card{rank='10', shit='♥'}, Card{rank='K', shit='♣'}]

认识Comparator

代码格式

public interface Comparator<T> { 
    // 返回值: 
    // < 0: 表示 o1 指向的对象小于 o2 指向的对象
    // == 0: 表示 o1 指向的对象等于 o2 指向的对象 
    // > 0: 表示 o1 指向的对象等于 o2 指向的对象      
    int compare(T o1, T o2); }

实例

//定义一个匿名内部类就行判断大小
        Collections.sort(list, new Comparator<Card>() {
            @Override
            public int compare(Card o1, Card o2) {
                int o1Rank = o1.rankToInt(o1.rank);
                int o2Rank = o2.rankToInt(o2.rank);
                return o1Rank - o2Rank;
            }
        });

测试

[Card{rank='10', shit='♥'}, Card{rank='A', shit='♠'}, Card{rank='K', shit='♣'}, Card{rank='A', shit='♣'}]
[Card{rank='A', shit='♠'}, Card{rank='A', shit='♣'}, Card{rank='10', shit='♥'}, Card{rank='K', shit='♣'}]

差异

  • 重写equals
    因为所有类都是继承自object类型,所以自己重写即可,不过只能判断是否相等。

  • 重写compareTo
    需要手动实现接口,侵入性强,一旦实现,每次用该类都有此顺序,属于内部顺序,而且一个比较对象,只能实现一种比较规则,而且比较的是库的类或者不是自己写的类就难以实现比较。

  • 重写compare
    需要实现一个比较器对象,对比较类的侵入性低,可以对一个比较的类实现多种比较方法,比Comparable适用范围更加广泛。

与集合框架的配合

  1. 使用 contains 类似的方法,内部基本在调用元素的 equals 方法,所以要求元素覆写过 equals 方法
  2. 使用 HashMap,key 的比较内部会调用 equals 方法,所以要求元素覆写过 equals 方法
  3. 使用排序相关方法,内部需要进行比较,所以或者选择实现 Comparable 或者传入一个 Comparator
  4. 使用 TreeMap,key 需要进行大小比较,所以或者选择实现 Comparable 或者传入一个 Comparator
  5. 其他规则以此类推

猜你喜欢

转载自blog.csdn.net/Shangxingya/article/details/106041245
今日推荐