Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何生成高效的哈希代码?_Java_Performance_Hashcode - Fatal编程技术网

Java 如何生成高效的哈希代码?

Java 如何生成高效的哈希代码?,java,performance,hashcode,Java,Performance,Hashcode,我有三种hashCode方法,如下所示,我根据它们的效率对它们进行了优先级排序。我想知道是否有其他方法可以使hashCode方法更有效 1) public int hashCode() { //terrible return 5; } 2) public int hashCode() { //a bit less terrible return name.length; } 3) public int hashCode() { //better fi

我有三种hashCode方法,如下所示,我根据它们的效率对它们进行了优先级排序。我想知道是否有其他方法可以使hashCode方法更有效

1) public int hashCode() { //terrible
     return 5; 
   }
2) public int hashCode() { //a bit less terrible
     return name.length; 
   }
3) public int hashCode() { //better
     final int prime = 31;
     int result = 1;
     result = prime * result + ((name == null) ? 0 : name.hashCode());
     return result;
   }
我根据他们的效率对他们进行了优先排序

如果您所说的“效率”是指应用程序的性能,而不是与其他方法隔离的
hashCode
方法的延迟,那么您的列表是按升序效率排序的。分散性差的哈希代码将导致通过
HashMap
中的链接列表进行线性或近似线性搜索,从而完全取消哈希表的优势


特别要注意的是,在今天的体系结构上,计算比指针解引用便宜得多,而且成本固定。一次缓存未命中相当于一千次简单的算术运算,每个指针取消引用都是一次潜在的缓存未命中。

没有可靠的方法保证您的
hashcode
函数是最优的,因为它是由两个不同的度量来衡量的

  • 效率计算速度有多快
  • 碰撞-碰撞的可能性有多大
你的:

  • 以碰撞为代价最大限度地提高效率
  • 发现中间有一个点,但仍然不好。
  • 效率最低但最适合避免碰撞-仍然不一定最好
  • 你必须自己找到平衡点

    有时,当有一种非常有效且从不冲突的方法时(例如
    枚举
    序数
    ),这一点是显而易见的

    有时,记住这些值是一个很好的解决方案——通过这种方式,即使是非常低效的方法也可以得到缓解,因为它只计算一次。这有一个明显的理论成本,也必须加以平衡

    有时,代码的整体功能会影响您的选择。假设要将
    文件
    对象放入
    哈希映射
    。有许多选择是明确的:

  • 使用文件名的哈希代码
  • 使用文件路径的哈希代码
  • 使用文件内容的crc
  • 使用文件内容的SHA1摘要的哈希代码
  • 为什么碰撞不好

    hashcode
    的主要用途之一是将对象插入到
    HashMap
    中。该算法从对象请求一个哈希代码,并使用该哈希代码决定将对象放入哪个bucket。如果散列与另一个对象发生冲突,则该存储桶中将有另一个对象,在这种情况下,存储桶将必须增长,这需要花费时间。如果所有散列都是唯一的,那么映射将是每个bucket一个项,因此效率最高


    有关
    HashMap
    如何工作的深入讨论,请参阅上的优秀WikiPedia文章。

    我的答案走了一条不同的道路-基本上,这不是答案,而是一个问题:为什么要担心
    hashCode()
    的性能

    您是否对您的应用程序进行了详尽的分析,并发现在某些对象上存在源于该方法的性能问题

    如果这个问题的答案是“不”。。。那么-为什么你认为你需要担心这个方法呢?为什么您认为eclipse生成的默认值可能每天使用数十亿次。。。对你来说还不够好吗


    请参阅,了解为什么在这些问题上浪费时间通常是一个非常糟糕的主意

    是的,有更好的选择


    或者是速度更快、质量更好的通用哈希算法。

    除了迄今为止有价值的答案之外,我还想添加一些其他方法来考虑:


    3a):

    在性能方面没有太多的优点/缺点,但更简洁一些


    4.)您应该提供更多关于您正在谈论的类的信息,或者重新考虑您的设计。但是,当类的唯一属性是
    字符串时,使用类作为哈希映射的键,那么您也可以直接使用该字符串。因此,选择4是:

    // Changing this...
    Map<Key, Value> map;
    map.put(key, value);
    Value value = map.get(key);
    
    // ... to this:
    Map<String, Value> map;
    map.put(key.getName(), value);
    Value value = map.get(key.getName());
    
    当然,这只对不可变类有意义。您应该知道,使用可变类作为
    Map
    的键是“危险的”,可能会导致一致性错误,并且只有在绝对确定用作键的实例不会更改时,才应该这样做

    因此,如果您想使用类作为键,并且您的类甚至可能不止一个字段,那么您可以将哈希代码存储为字段:

    class Key 
    {
        private final String name;
        ... // Other fields...
    
        private final int hashCode;
    
        Key(String name, ...)
        {
            this.name = name;
            ... // Other fields
    
            // Pre-compute and store the hash code:
            this.hashCode = computeHashCode();
        }
    
    
        private int computeHashCode()
        {
            int result = 31;
            result = 31 * result + Objects.hashCode(name);
            result = 31 * result + ... // Other fields
            return result;
        }
    }
    

    第一个刚回来…5。。那威尼斯有什么好处?旁注:
    name.length
    一点也不好,也没那么可怕:为什么不自动生成它?这里有一个新颖的想法。。。返回name.hashCode()怎么样。唯一影响hashcode的似乎是
    name
    的值。如果它是一个
    字符串
    ,它将返回一个好的hashcode。编辑:显然它不是一个
    字符串,而是一个数组。您可以返回它的hashcode,也可以使用
    Arrays.hashcode()
    生成它。效率是一个主观的衡量标准,在很大程度上取决于上下文。是否需要在散列数据结构中快速插入和/或查找?输入数据的分布特征是什么?大多数情况下,在遇到性能问题并查明实际瓶颈之前,不要尝试进行优化。感谢您的回答,请详细说明指针解引用?另外,我有点搞不清哪一个更好?在Java级别上,只要访问一个对象(读取对它的引用,然后从它指向的内存位置读取),指针解引用就会发生。最好的哈希代码是3),因为它将导致哈希表中条目的最佳分布,使它们可以在O(1)时间而不是O(n)时间内访问
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        ...
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0
    
    class Key 
    {
        private final String name;
        ... // Other fields...
    
        private final int hashCode;
    
        Key(String name, ...)
        {
            this.name = name;
            ... // Other fields
    
            // Pre-compute and store the hash code:
            this.hashCode = computeHashCode();
        }
    
    
        private int computeHashCode()
        {
            int result = 31;
            result = 31 * result + Objects.hashCode(name);
            result = 31 * result + ... // Other fields
            return result;
        }
    }