【问题标题】:How to get() specific element from HashSet? Kotlin如何从 HashSet 中获取()特定元素?科特林
【发布时间】:2020-06-18 16:42:39
【问题描述】:

假设myHashSet = HashSet<SomeClass>

在哪里SomeClass.hashcode() = someField.hashcode()

如何返回具有指定哈希码的元素,即:

myHashSet.getElementWithHashCode((other as SomeClass).someField.hashcode())

other和HashSet里面的对象是不同的对象,除了someField的值外,属性值也不同。换句话说,这两种不同类型的对象有一个可能具有相同值的公共字段。

奇怪的是HashSet中没有这个函数。以前没人需要吗?最快的方法是什么?

【问题讨论】:

  • 您可以使用find 或first 等函数搜索集合中的元素。将标准作为 lambda 传递给它:mySet.find { it.hashcode() == other.hashcode() }.
  • @MalteHartwig 是的。有效。实际上,这就是 getItem() 函数在内部的作用。所以我想性能不会受到影响。如果您将其写为答案,我可以接受。
  • 不行,性能肯定会受到影响;例如如果没有具有您想要的哈希码的元素,它将遍历整个集合。
  • @AlexeyRomanov 对。这与使用键直接从内存中获取值不同。那么有没有办法使用哈希码从关键位置获取元素呢?
  • 我给出了答案。

标签: android kotlin hashset


【解决方案1】:

没有标准解决方案;但由于 HashMap.get(key) 指定它将参数与存储的密钥 (key.equals(k)) 进行比较,而不是相反,因此您可以通过这种讨厌的 hack 获得所需的结果(讨厌,因为它违反了 equals 合同):

class HasHash(private val hash: Int) {
    override fun hashCode() = hash
    override fun equals(other: Any?) = other != null && other.hashCode() == hash
}

但即便如此,JVM 上的 HashSet 也不会暴露您需要的细节(例如 getElement in Kotlin/Native),所以我能想出的唯一解决方案是

val set: HashSet<T> = ...
val map: Map<Any, T> = set.associateBy { it }

fun findByHashCode(hash: Int): T? = map[HasHash(hash)]

它需要遍历set 来构造map,但只需要一次,因此如果您需要在单个集合中查找许多元素,它仍然很有用。

在 Kotlin/Native 中只是

fun <T> HashSet<T>.findByHashCode(hash: Int): T? = getElement(HasHash(hash))

此外,如果集合中有多个具有所需哈希码的元素,您只会得到其中一个。

所以您将每个项目都以自身作为键进行映射?是不是说 associateby{} 自动将元素的 hashcode() 作为 key

没有。这个想法是:

  1. 说set 包含"a"(哈希码1;并非如此,但在本例中假设如此)、"b"(哈希码1)和"c"(哈希码2) .

  2. 那么map就是"a": "a", "b": "b", "c": "c"。

  3. 致电findByHashCode(1) = map[HasHash(1)]。

  4. HasHash(1) 的哈希码是 1,因此它会查找包含键 "a" 和 "b" 的插槽(假设按此顺序)。 HasHash(1).equals("a") 返回true,因此返回了与键"a" 存储的值,即"a"。

还是getElement()函数根据输入元素的hashcode自动检查?

它说的是什么

返回集合中与元素相等的元素,如果没有找到这样的元素,则返回 null。

所以它应该返回"a" 如果它会按顺序比较它们HasHash(1).equals("a")。

【讨论】:

  • 无法理解(this as HashSet&lt;Any&gt;)[HasHash(hash)] 部分。不知道我以前是否见过这样的语法。
  • 哪一部分? this 是您在扩展函数中引用接收器参数的方式,as 是强制转换,[...] 是 get 方法的语法糖。
  • 所以你使用了get(HasHash(hash))。但在 Android Studio 的 HashSet 对象的建议列表中没有 get() 方法。
  • 糟糕,我把它和Map API 混在一起了。如此固定,但有一个额外的坏限制:(
  • 所以您将每个项目都以自身作为键进行映射?是associateby{}自动将元素的hashcode()作为key还是getElement()函数自动根据输入元素的hashcode进行检查?因为输出不应该是 HasHash(hash) 本身,而是它的 hashTwin。
【解决方案2】:

我不知道this 是否适合您,这取决于它在内部使用的是hashCode 还是equals。一些有类似问题的在线sources 正在寻找基于平等的解决方案。

无论如何,你可以使用像find或first这样的内置函数来自己实现它:

fun <E> HashSet<E>.findByHashCode(other: E): E? = firstOrNull { it.hashCode() == other.hashCode() }

【讨论】:

    猜你喜欢
    • 2022-09-26
    • 2023-02-14
    • 1970-01-01
    • 2021-05-11
    • 2021-05-09
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多