Java 来自字段字符串concat的Hashcode与自动生成的方法

Java 来自字段字符串concat的Hashcode与自动生成的方法,java,hash,hashmap,collision,hashcode,Java,Hash,Hashmap,Collision,Hashcode,如果我们有如下类别: class ConnectedPair { private String source; private String destination; public ConnectedPair(String source, String destination) { if(source == null || destination == null) { throw new

如果我们有如下类别:

class ConnectedPair {
        private String source;
        private String destination;

        public ConnectedPair(String source, String destination) {
            if(source == null || destination == null) {  
                throw new NullPointerException();
            }
            this.source = source;
            this.destination = destination;
        }
}  
@Override
public int hashCode() {
    return (source + "=>" + destination).hashCode();
}  
我们想在
HashMap
HashSet
中使用它,我们需要实现
等于
hashCode

此类自动生成的
hashCode
为:

@Override
public int hashCode() {
    int result = source.hashCode();
    result = 31 * result + destination.hashCode();
    return result;
}  
但我想知道我们是否做了以下工作:

class ConnectedPair {
        private String source;
        private String destination;

        public ConnectedPair(String source, String destination) {
            if(source == null || destination == null) {  
                throw new NullPointerException();
            }
            this.source = source;
            this.destination = destination;
        }
}  
@Override
public int hashCode() {
    return (source + "=>" + destination).hashCode();
}  
这比自动生成的方法好还是坏?正如我所看到的,其他脚本语言也在使用类似的方法,我想知道生成的哈希是更好还是更差(或者没有区别)

注意:假设字符串concat可以缓存并进行优化,那么我们就忽略它,因为它会降低性能

  • 如果您所关心的只是一个有效的实现,并且对于意外和/或故意碰撞的可能性没有具体的要求,那么它们都很好。这是大多数案件:你可以在这里停止调查
  • 这两种方法都受到
    String.hashCode()
    的糟糕定义的影响。由于历史原因,
    String.hashCode()
    对其工作方式有一个固定的定义,该定义是。。。糟糕。它很容易发生意外碰撞,并且很容易构造有意碰撞
  • 第二个(使用字符串连接)使得使用相同的哈希代码(
    newconnectedpair(“a=>b”,“c”).hashCode()==newconnectedpair(“a”,“b=>c”).hashCode()构造两个
    ConnectedPair
    对象变得非常简单。另一个选项并不能完全阻止这一点,但会使构建样本稍微困难一些
  • 这听起来可能很傻,但生成的代码是惯用的:每个看到这段代码的Java开发人员都会很快理解您在做什么。您的“定制”实现看起来并没有太糟糕,但需要稍微多一些脑力来解析。请记住:代码的阅读频率要比编写频率高得多
  • 如果您所关心的只是一个有效的实现,并且对于意外和/或故意碰撞的可能性没有具体的要求,那么它们都很好。这是大多数案件:你可以在这里停止调查
  • 这两种方法都受到
    String.hashCode()
    的糟糕定义的影响。由于历史原因,
    String.hashCode()
    对其工作方式有一个固定的定义,该定义是。。。糟糕。它很容易发生意外碰撞,并且很容易构造有意碰撞
  • 第二个(使用字符串连接)使得使用相同的哈希代码(
    newconnectedpair(“a=>b”,“c”).hashCode()==newconnectedpair(“a”,“b=>c”).hashCode()构造两个
    ConnectedPair
    对象变得非常简单。另一个选项并不能完全阻止这一点,但会使构建样本稍微困难一些
  • 这听起来可能很傻,但生成的代码是惯用的:每个看到这段代码的Java开发人员都会很快理解您在做什么。您的“定制”实现看起来并没有太糟糕,但需要稍微多一些脑力来解析。请记住:代码的阅读频率要比编写频率高得多

  • 关于(1)这是否意味着我们应该完全避免
    String.hashCode()
    ?因此,对于这个只有
    String
    字段的特定类,如何替换它?@Jim:see#0:这些问题都不是主要问题,通常根本不重要。它们可能会出现问题,具体取决于您如何使用它们(例如,如果不受信任的用户可以自由添加元素,而您将它们全部保存到
    HashMap
    中,那么它们可能会导致大量冲突并降低系统性能)。换句话说:您的实现在“好的”
    Object.hashCode
    实现的一般区域。即使是最好的
    hashCode
    实现也远未达到真正加密哈希的黄金标准,这通常是很好的。那么这只是一个理论问题吗?我会想,除了我实际上遇到了“降级”/由于在另一种情况下与int对发生冲突而导致的性能差,其中数据只是有一个特定的“结构”,即,如果你有时间,这里检查所有1000点对,这是一个纯理论性的问题,直到它没有出现。在正常操作中,这应该是正常的,但是有一天你会意识到用户可以与你的公共服务器交互,JDK没有修补到最新版本,并且持有一些内部缓存的
    HashMap
    会向线性扫描模式崩溃,有效地运行DOS攻击。我并不是说这是可能的,事实上,我认为第#0项是我的答案中最相关的一项,但这是可能的。关于(1)这是否意味着我们应该完全避免
    String.hashCode()
    ?因此,对于这个只有
    String
    字段的特定类,如何替换它?@Jim:see#0:这些问题都不是主要问题,通常根本不重要。它们可能会出现问题,具体取决于您如何使用它们(例如,如果不受信任的用户可以自由添加元素,而您将它们全部保存到
    HashMap
    中,那么它们可能会导致大量冲突并降低系统性能)。换句话说:您的实现在“好的”
    Object.hashCode
    实现的一般区域。即使是最好的
    hashCode
    实现也远未达到真正加密哈希的黄金标准,这通常是很好的。那么这只是一个理论问题吗?我会想,除了我实际上遇到了“降级”/由于在另一种情况下与int对发生冲突而导致的性能差,其中数据只是有一个特定的“结构”,即,如果你有时间,这里检查所有1000点对,这是一个纯理论性的问题,直到它没有出现。在正常操作中,它应该是好的,但有一天你会意识到用户可以交互