博客
关于我
不要使用可变对象作为键
阅读量:624 次
发布时间:2019-03-14

本文共 1710 字,大约阅读时间需要 5 分钟。

hashCode方法中的不可变属性之争

在编写Java类的equals和hashCode方法时,选择对象属性是可变的还是不可变的,直接关系到类在集合操作中的行为和性能。这一选择背后有着深厚的技术考量,本文将从原理与实际应用两个层面探讨这一问题。

##Storyboard

###不可变属性的优势

StringBuilder类选择继承Object的hashCode方法,这一选择背后有着深刻的技术原因。实际上,StringBuilder的属性是可变的,它的car次数组可以被修改。然而,它并没有重写hashCode方法。这是为什么呢?通过分析等 Rentals

从理论上讲,当类的属性是可变的时,getHashCode()方法的结果可能会因为属性的变化而变化. 此时, 当该对象被添加到集合中时, 集合记录它的唯一标识符(即hashCode值)也是该值. 如果这个值随着时间的推移发生改变, 根据集合中的存储机制, 操作可能会遇到问题.

例如, 当HashTest类包含可变属性时, 它在被添加到集合之后, 可能会因为可变属性的改变而在集合中位置失准, 导致contains()方法返回false, 虽然对象仍然存在. 这是一个令人不舒服的情况.

这个时候, 为什么String类选择可变属性重写hashCode方法呢?因为String类的属性是final,不能被修改. 这使得其每次调用hashCode方法所产生的值都是一样的,从而保证了性能和一致性.

而StringBuilder继承自Object, 因此其重写当然继承了Object的默认hashCode方法, 这也是为什么它可以保持与其他对象一致性的原因.

###对可变属性的潜在风险在HashTest类的例子中, 可变属性导致的问题已经非常突出. 当集合记录对象的位置是基于初始的hash值计算的, 而当object的可变属性发生改变后, 她们的位置自然会出现偏移. 这是不够的,因为在集合操作中, 记录的位置将与其关联的对象值不再保持同步.

这不是说可变属性不能发挥作用, 而是说它们在equals和hashCode方法中不能随意应用. 只有在满足以下条件时才可以使用可变属性:

  • 类内部的一致性得到保留, 可变属性不会导致对象的比较逻辑混乱
  • 而且这种一致性也可以在集合的环境中保持不变, 这可能不现实
  • 事实上, 这种情况的典型表现是未经意中改变对象的identity, 但由于集合中的记录机制并未抓住这点而导致问题发生. 这种现象引人深思.

    ###性能考量对于一个拥有大量可变属性的类来说, 每次修改属性都会导致两个重要的方面产生影响:

  • 对于单个属性的修改操作,可能会重新计算并存储新的hash值和相等的值
  • 对于整个集合来说, 则需要用这些修改带来的新的值去重新处理这两个操作
  • 这不仅会导致性能下降,而且也可能导致编写这样的类更加困难. 从另一方面来看, String类因为属性不可变,所以无需为每个修改操作做任何事情. 这始终是一个重要的不争的事实.

    从这个角度来说, 在大多数情况下, 可变属性在equals和hashCode方法中的使用都是可以避免的. 只有当你完全确定所有状态的变化都不会引起等价性(equal)的变化时, 才可以依靠它们.

    ###改进建议为了避免在集合中的行为异常,建议在设计类时尽量避免使用可变属性, 或者在已有类哪里的情况下,明确规定类的状态变化不影响equal和hashcodemic存的计算方式.

    因此, my建议是这样:

  • 对于对象属性尽可能选择不可变的方式
  • 如果必须使用可变属性, 那么在重写equals和hashCode方法时, 必须使用公式化的方式, 确保每一次相同的数据状态都会产生相同的等价性判断和哈希代码
  • 这些方法论将确保在集合操作中拥有可靠和可预测的行为.

    ##总结在编写Java类的equals和hashCode方法时,应尽量尽量避免使用可变属性. 如果无法避免, 就必须采用严格的公式化方式来确保一致性和可逆性. 这样不仅能够确保 Collection类别的正确操作,也可以提高整体应用程序的性能和可维护性.

    转载地址:http://fwxoz.baihongyu.com/

    你可能感兴趣的文章
    【模拟】ZOJ Problem Set - 3490 String Successor
    查看>>
    【母函数初学,其他简便方法】Holding Bin-Laden Captive! hdoj 1085
    查看>>
    【思维】hdu 5832 A water problem 2016icpc网络赛
    查看>>
    hdu 5878 I Count Two Three(二分)
    查看>>
    王道数据结构2.2.3——13、找出整数数组中未出现的最小正整数
    查看>>
    王道数据结构2.2.3——16、判断一个单链表是否为另一个单链表的连续子序列
    查看>>
    C++版浙大PAT乙级1069(20分)测试点3答案错误解决方法
    查看>>
    微信小程序-动态列表项的顺序加载动画
    查看>>
    浙大数据结构——4.2平衡二叉树
    查看>>
    SpringBoot(十三) 集成消息队列RocketMq
    查看>>
    SpringBoot(一) 入门及搭建方法
    查看>>
    CentOS 7 Failed to start LSB: Bring up/down networking
    查看>>
    将100以内的所有质数输出
    查看>>
    hive内部错误
    查看>>
    Error during export: Export job failed! sqoop遇到的错
    查看>>
    Error:scalac: bad option: '-make:transitive'
    查看>>
    引用外部jQuery地址
    查看>>
    微软xp壁纸rgb
    查看>>
    浏览器刷新页面
    查看>>
    HTML5本地存储localStorage,sessionStorage
    查看>>