热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

布尔字段的哈希码实现

如何解决《布尔字段的哈希码实现》经验,为你挑选了1个好方法。

如果有两个布尔字段,我如何实现一个好的哈希码?通常人们只是将整数值添加到其哈希码值中.但是,如果我只是在我的哈希码中添加1或0,我认为它不好.因为如果我有两个A类对象:

obj1.b = true,obj1.c = false.

obj2.b = false,obj2.c = true.

其他一切都是一样的.然后这两个不等对象的哈希码是相同的.我知道这种情况还可以.但想象一下,如果有100个布尔字段,那么会有太多的碰撞对吗?我不希望这么多不同的对象落入同一个桶中.

我在下面做的是为每个字段的不同真值分配不同的数字,因此对象的哈希码可能非常不同.

public class A {

    private final String a;
    private final boolean b;
    private final boolean c;

...

@Override public int hashCode(){
            int i,j;
            if(b) {
                    i = 10;
            }
            else {
                    i = 0;
            }
            if(c) {
                    j = 88;
            }
            else {
                    j = 3;
            }
            int result = 0;
            result = 31*result + i + j;
            result = 31*result + (a != null ? a.hashCode() : 0);
            return result;
    }
}

Jon Egeland.. 9

你有几个选择:

选项1:位标记

最好的办法,以保证有可能永远不会为布尔的哈希值之间的碰撞是使用一个类似于中所使用的技术有点萎靡不振,因此你必须每个布尔占据自己的位.例如:

// `byte` can be replaced with `short`, `int`, or `long` to fit all of your variables.
byte = 0;
if(bool1) booleans += 1;  // 0001
if(bool2) booleans += 2;  // 0010
if(bool3) booleans += 4;  // 0100
if(bool4) booleans += 8;  // 1000
...

然而,这种方法在大量布尔值的情况下很快变得低效,并且高度依赖于目标阵列的大小.例如,如果您有一个大小为16的目标数组,则只有前4个对哈希值有影响(因为最大索引是1111).

对此的两个解决方案是增加目标数组的大小(可能不在您的控制之下),或者确保您的布尔值的顺序从大多数变为最小变量.这些都不是最佳的,因此这种方法快速简便,但在实践中效果不是很好.

选项2:基础更改哈希

Pham Trung在他的回答中展示的设计扩展了选项1,作为容纳多个领域的简单方法.正如Adrian Shum所评论的那样,这个答案提供了一个"通用散列算法"的概述,它被设计为独立于你想要散列的内容而有效.

基本思想是将每种类型的简化哈希值乘以一些任意大的素数,以确保每个哈希值都是唯一的(尽管证明了这一点可以避免我).例如:

int result = 0;
result = 31*result + bool1 ? 1 : 0;
result = 31*result + bool2 ? 1 : 0;
...

对于更稀疏的散列分布,您可以将其与其结合使用Boolean.hashCode,如其他答案所示:

int result = 0;
result += 31*result + bool1.hashCode();
result += 31*result + bool2.hashCode();
...

这个解决方案的优点在于它可以应用于其他类型,就像您在示例代码中已有的那样:

...
result = 31*result + i;
result = 31*result + (a != null ? a.hashCode() : 0);
result = 31*result + my_complex_object.hashCode();

注意:在这些例子中,31只是一些任意素数.你可能只是很容易地使用37,11323456789.但是,使用较大的被乘数会有一些权衡,即你的哈希值会更快地超过Integer.MAX_VALUE你的哈希并使你的哈希值无效.



1> Jon Egeland..:

你有几个选择:

选项1:位标记

最好的办法,以保证有可能永远不会为布尔的哈希值之间的碰撞是使用一个类似于中所使用的技术有点萎靡不振,因此你必须每个布尔占据自己的位.例如:

// `byte` can be replaced with `short`, `int`, or `long` to fit all of your variables.
byte = 0;
if(bool1) booleans += 1;  // 0001
if(bool2) booleans += 2;  // 0010
if(bool3) booleans += 4;  // 0100
if(bool4) booleans += 8;  // 1000
...

然而,这种方法在大量布尔值的情况下很快变得低效,并且高度依赖于目标阵列的大小.例如,如果您有一个大小为16的目标数组,则只有前4个对哈希值有影响(因为最大索引是1111).

对此的两个解决方案是增加目标数组的大小(可能不在您的控制之下),或者确保您的布尔值的顺序从大多数变为最小变量.这些都不是最佳的,因此这种方法快速简便,但在实践中效果不是很好.

选项2:基础更改哈希

Pham Trung在他的回答中展示的设计扩展了选项1,作为容纳多个领域的简单方法.正如Adrian Shum所评论的那样,这个答案提供了一个"通用散列算法"的概述,它被设计为独立于你想要散列的内容而有效.

基本思想是将每种类型的简化哈希值乘以一些任意大的素数,以确保每个哈希值都是唯一的(尽管证明了这一点可以避免我).例如:

int result = 0;
result = 31*result + bool1 ? 1 : 0;
result = 31*result + bool2 ? 1 : 0;
...

对于更稀疏的散列分布,您可以将其与其结合使用Boolean.hashCode,如其他答案所示:

int result = 0;
result += 31*result + bool1.hashCode();
result += 31*result + bool2.hashCode();
...

这个解决方案的优点在于它可以应用于其他类型,就像您在示例代码中已有的那样:

...
result = 31*result + i;
result = 31*result + (a != null ? a.hashCode() : 0);
result = 31*result + my_complex_object.hashCode();

注意:在这些例子中,31只是一些任意素数.你可能只是很容易地使用37,11323456789.但是,使用较大的被乘数会有一些权衡,即你的哈希值会更快地超过Integer.MAX_VALUE你的哈希并使你的哈希值无效.


推荐阅读
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
author-avatar
王老虎在江湖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有