2016-07-26 8 views
1

Я ищу встроенные альтернативы HashSet и Dictionary объектов, которые имеют лучшую производительность, чем списки, но не используют внутренний метод GetHashCode. Мне это нужно, потому что в классе я написал, что нет никакого способа написания GetHashCode метод, который выполняет обычный контракт с Equals кромеC# перманентные альтернативы HashSet и словарь, которые не используют GetHashCode

public override int GetHashCode() { return 0; } // or return any other constant value 

, который превратит HashSet и Dictionary в обычные списки (производительность мудрая) ,

Так что мне нужна реализация набора и реализация отображения. Какие-либо предложения?

EDIT:

Мой класс является допуск на основе 3-мерный вектор класс:

public class Vector 
{ 
    private static const double TOL = 1E-10; 
    private double x, y, z; 

    public Vector(double x, double y, double z) 
    { 
     this.x = x; this.y = y; this.z = z; 
    } 

    public override bool Equals(object o) 
    { 
     Vector other = o as Vector; 

     if (other == null) 
      return false; 

     return ((Math.Abs(x - other.x) <= TOL) && 
       (Math.Abs(y - other.y) <= TOL) && 
       (Math.Abs(z - other.z) <= TOL)); 
    } 
} 

Обратите внимание, что мой Equals метод не является транзитивным. Однако в моем случае я могу сделать его «локально» транзитивным, потому что в какой-то момент я узнаю все векторы, которые мне нужно поместить в набор set/mapping, и я также знаю, что они появятся в кластерах. Поэтому, когда я собрал все векторы, я выберу одного представителя для каждого кластера и заменит все оригинальные векторы представителем. Затем Equals будет транзитивным среди элементов моего набора набора/набора карт.

Когда у меня есть мой набор или сопоставление, я буду собирать векторы из другого источника (для этого вопроса давайте предположим, что я попрошу пользователя ввести вектор). Это может быть любой возможный вектор. Они никогда не будут добавлены в набор/сопоставление, но мне нужно будет знать, содержатся ли они в наборе/наборе ключей отображения (относительно толерантности), и мне нужно будет узнать их значение из сопоставления.

+1

Вам потребуется предоставить дополнительную информацию об объекте. Почему вы не можете создать хеш для этого? Что вы можете сообщить об этом? Как вы сравниваете объекты для равенства и т. Д. – Servy

+1

'SortedSet' и' SortedDictionary' –

+0

@IvanStoev Предполагается, что объекты имеют согласованное полное упорядочение. – Servy

ответ

-2

В вашем случае вы можете получить достаточно хорошую реализацию hashcode. Помните, что самое важное правило для хэш-кода следующие:

  • Две равные векторы сусло возвращают то же значение

Это не означает, что два различных вектора не могут возвращать тот же стоимость; они, очевидно, должны в некоторых случаях, количество хешей ограничено, число отдельных векторов для всех целей - нет.

Ну, с учетом этого, просто оцените свой хэш-код, основанный на координатах векторов, усеченных до значащих цифр толерантности минус один. Все равные векторы дадут вам один и тот же хэш и небольшое меньшинство не равных векторов, которые отличаются последним десятичным значением ... вы можете жить с этим.

ОБНОВЛЕНИЕ: Изменено округлено до усеченного. Округление не является правильным выбором.

+0

Это не тот случай. Округления недостаточно. Предположим, что у вас есть допущение 5 единиц. Затем скажем, что у меня есть элемент со значением 7. Если вы просто округлите до ближайшего кратного 5, то у 7 будет хеш 5. Далее посмотрим 11. У него будет хэш из 10, но он «равен "до 7, и все же он имеет другой хеш. Округление просто не может работать для равноправия, основанного на терпимости, потому что в основном должна быть точка округления, поэтому вы всегда можете выбрать два элемента по обе стороны от округлой точки в пределах порога друг друга. – Servy

+0

Нет, не работает. Потому что 'Equals' не является транзитивным. Возьмите вектор (0,0,0) и (1E-10, 1E-10, 1E-10). Они равны в соответствии с моей реализацией. Поэтому они должны вернуть тот же HashCode. Возьмите вектор (1E-10, 1E-10, 1E-10) и (2 * 1E-10, 2 * 1E-10, 2 * 1E-10). Они снова равны, поэтому они должны возвращать тот же HashCode. И так далее, и так далее. Таким образом, единственный способ соответствовать контракту «HashCode» и «Equals» - реализовать «GetHashCode» как постоянную функцию. – Kjara

+0

@Servy: Он по-прежнему является допустимым хешем, он может быть не очень хорошим, и, очевидно, это не больше TOL, но все дело в том, что 'TOL' достаточно мал. Ваш пример несправедлив, потому что вы в основном используете интегральные контрпримеры, которые в контексте этого вопроса не имеют смысла – InBetween