当前位置: 首页 > 知识库问答 >
问题:

为什么没有碰撞?

刁丰羽
2023-03-14

我正在与Kotlin研究地图,并决定运行以下代码:

fun main() {
    data class KeyClass(val equals: String, val hash: Int) {
        override fun equals(other: Any?): Boolean {
            return this.equals == (other as KeyClass).equals
        }

        override fun hashCode(): Int {
            return hash
        }

        override fun toString(): String {
            return "($equals,$hash)"
        }
    }

    // collision, since their hashes are the same but they are not equal
    val a1 = KeyClass("a", 1)
    val a2 = KeyClass("b", 1)
    val map = HashMap<KeyClass, String>()
    map[a1] = "value1"
    println(map)
    map[a2] = "value2"
    println(map)

    val map2 = mutableMapOf<KeyClass, String>()
    map2[a1] = "value1"
    println(map2)
    map2[a2] = "value2"
    println(map2)
}

这让我:

{(a,1)=value1}
{(a,1)=value1, (b,1)=value2}
{(a,1)=value1}
{(a,1)=value1, (b,1)=value2}

我以为HashMap的冲突导致了一个列表。然后当我尝试MutableMapOf这是静态编程语言的LinkedHashMap时,我也没有得到任何冲突。

问题:

  1. 我在这个简单的碰撞示例中错过了什么?
  2. 每个Map实现最常见的冲突行为是什么?

共有2个答案

梁磊
2023-03-14

您确实发生了冲突。结果可能与您预期的不同。您遇到了hashCode冲突,这只会减慢地图的插入和检索时间。我认为您希望地图只包含1个条目,但即使hashcode与键的相等值匹配,但不匹配,所以您仍然在地图中放置2个不同的键,产生2个条目。

赖渊
2023-03-14

你说的这个列表是一个内部实现细节。你不能告诉*这是在映射的内部发生的事情,这是封装的重点。

观察碰撞的唯一方法是计时。因此,制作一百万个字符串,将它们塞进映射中,然后在其中的条目上运行. tainsKey()几次。

然后,重复这个练习,但这一次,让一百万个对象发生碰撞(相同的哈希代码)。然后再次运行。containsKey()在其中的条目上重复几次。

您会注意到,第二个操作返回完全相同的答案,但运行速度要慢得多,这是您将观察到的唯一情况。

*)通过定时观测,你可以推测出它,但仅此而已。

 类似资料:
  • 问题内容: 我正在尝试做这样的事情: 不幸的是,即使在Java 9中也不存在。 为什么它被遗漏了? 建议的解决方法是什么? 问题答案: 为什么它被遗漏了? 该API提供了可重用的构建块。这里的相关积木是,,。通过这些,您可以实现所需的功能:将流内映射到对象,然后获得平面图。提供构建基块的排列是不切实际的,并且很难扩展。 建议的解决方法是什么? 如前所述,使用可用的构建基块(+ ):

  • 许多编译器都提供128位整数类型,但我使用过的编译器都没有提供typedefs。为什么? 据我回忆,标准 用于此目的的储量 鼓励提供此类类型的实现提供typedef 要求此类实现提供至少128位的intmax_t (而且,我不相信我使用了实际上符合最后一点的实现)

  • 问题内容: 我知道每次键入字符串文字时,字符串池中都会引用相同的String对象。 但是,为什么String API不包含,所以我可以使用引用? 至少,这将节省编译时间,因为编译器将知道引用现有的String,而不必检查是否已创建它以进行重用,对吗?我个人认为,字符串文字(尤其是很小的文字)在许多情况下是一种“代码异味”。 那么是否没有String.Empty背后的宏伟设计原因,还是语言创建者根本

  • 问题内容: Java的标准库似乎使用camelCase作为方法名称。诸如此类的本 机 功能也不例外。 如果是这样,为什么 不驼峰? 有什么特别的吗? 问题答案: 它已经在Java中的1.0版本发布之前-所以我的猜测是,它早于命名约定,它是在API的横扫无缘当命名约定 进行 确定。 (在其他新闻中,应称为。)

  • 问题内容: 在Java中,有和接口。两者都属于Java的标准框架,并提供了一种访问元素的分类方法。 但是,据我了解没有。你可以用来对列表进行排序。 知道为什么要这样设计吗? 问题答案: 列表迭代器首先确保你以列表的内部顺序(也称为插入顺序)获取列表的元素。更具体地说,它是按照插入元素的顺序或操作列表的方式进行的。排序可以看作是对数据结构的一种操作,有几种方法可以对列表进行排序。 我将按照自己的见解

  • 问题内容: 我正在探索,惊讶地发现那没有。 我有两个问题。 主要问题 我想知道为什么删除了? 是否存在性能问题或其他问题? 次要问题 我解决我的问题写我的: 这样可以/有更好的方法吗? 问题答案: