Как получить () указанный элемент c из HashSet? Kotlin - PullRequest
1 голос
/ 06 марта 2020

Предположим myHashSet = HashSet<SomeClass>, где SomeClass.hashcode () = someField.hashcode()

Как я могу вернуть элемент с указанным хеш-кодом, т.е.:

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

Элемент внутри HashSet и other это разные объекты с разными значениями свойств, кроме someField value.

Странно, что в HashSet такой функции нет. Никто не нуждался в этом раньше? Какой самый быстрый путь?

Ответы [ 2 ]

1 голос
/ 06 марта 2020

Там нет стандартного решения; но поскольку HashMap.get(key) указывает, что он сравнивает параметр с сохраненными ключами (key.equals(k)), а не наоборот, вы могли бы достичь желаемого результата с помощью этого неприятного хака (неприятного, потому что он ломает equals контракт):

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

Но даже тогда HashSet на JVM не раскрывает нужных вам деталей (например, getElement в 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 {} автоматически принимает хеш-код () элемента в качестве ключа

Нет. Идея такова:

  1. Say 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 () автоматически проверяет в соответствии с хэш-код элемента ввода?

Что он говорит:

Возвращает элемент из набора, равного элементу, или ноль, если такой элемент не найден.

, поэтому он должен вернуть "a" , если , он сравнивает их в порядке HasHash(1).equals("a").

0 голосов
/ 06 марта 2020

Я не знаю, может ли это в вашем случае, это будет зависеть от того, использовал ли он hashCode или equals для внутреннего использования. Некоторые источники онлайн, имеющие аналогичную проблему, ищут решение на основе равенства.

В любом случае, вы можете использовать встроенные функции, такие как find или first, чтобы реализовать его самостоятельно. :

fun <E> HashSet<E>.findByHashCode(other: E): E? = firstOrNull { it.hashCode() == other.hashCode() }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...