关于Java中equals方法

今天被这熟悉而又陌生的equals方法搞麻了。对于不可变类型,似乎还好,反正是不可变的,判断一下内容即可。主要是父类类型和子类类型之间做equals时,需要处理非常多的细节。但是把这种比较内容(也即是观察等价性)的想法用到可变类型上,可就掉坑里了。

一般借java讲等价性,都会提到,java的容器类型都实现了观察等价性。由于容器都是mutable的,嵌套的HashSet<ArrayList<String>>会出bug:

public static void main(String[] args) {
    HashSet<ArrayList<String>> set = new HashSet<>();
    ArrayList<String> list = new ArrayList<>();
    list.add("A");
    set.add(list);
    set.contains(list);  // return true
    list.add("B");
    set.contains(list);  // return false
}

list并没有移除可是contains检测不到了。这是因为list被改变了,按其观察等价性的实现,hashcode也变了,contains计算哈希桶编号得到的不再是原来的那个保存着list的桶了,自然认为找不到list。麻了。

在PPT上,关于这里,说java的观察等价性实现是不好的,应该使用行为等价性实现,即使用Object中引用等价性的实现。可是使用引用等价性完全不能反应这个ADT的任何特点,实际上没有任何意义。这样的equals实现无非是“不出bug”,并不能使它有意义地出现在HashSet中。在HashSet里出现两个地址不同但元素完全相同的东西看上去是荒谬的。目前java中的这些容器类型不能很好地容纳可变类型,主要还是在于不能随着元素变化自动调整容器自身,和equals怎样实现是没有关系的。无论是没有意义的引用等价性还是倒霉的观察等价性,都不能让容器正确地、反应ADT特性地容纳相关类型。搞坏了equals,再去弄一个same,similar之类的去判断ADT等价性属实麻了。

最简单的规则还是禁止在容器中使用可变类型。实在需要在容器中使用可变类型,还是封装remove-add好一点。让equals做回自己吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值