Сравнение HashSet <String>с String.equals (...) - PullRequest
2 голосов
/ 16 июня 2011

Если у меня есть установленное число String, которое я хочу проверить в поле свободной формы (генерируется компьютером, может быть много в секунду), что будет более быстрой реализацией?

private static HashSet<String> values = new HashSet<String>();
static {
   ... add 5 Strings to the Set
}
public void someMethod() {
   if (values.contains(enteredValue))
   ...
}

Или делать, если с 5 String.equals ||?

Мне кажется, что это легко, но, может быть, я ошибаюсь. Есть ли недостатки у одного, а не у другого?

Ответы [ 7 ]

5 голосов
/ 16 июня 2011

Я считаю, что HashSet будет быстрее, потому что он хеширует вашу строку один раз, а затем сделает 5 целочисленных сравнений.Это должно быть быстрее, чем делать 5 String сравнений.

При этом я предлагаю вам просто выбрать один из способов и попробовать его.Если он работает недостаточно быстро, подумайте о его оптимизации.

2 голосов
/ 16 июня 2011

String исходный код :

Хеш-код:

/** Cache the hash code for the string */
private int hash; // Default to 0

public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = 31 * h + val[off++];
        }
        hash = h;
    }
    return h;
}

Код равенства:

public boolean equals(Object anObject) {
    if (this  == anObject) {
        return true;
    }
    if (anObject instanceof  String) {
        String anotherString = (String) anObject;
        int n = count;
        if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
            return true;
        }
    }
    return false;
}

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

Мое интуитивное чувство таково, что если вы не сравниваете одни и те же строки с одними и теми же строками снова и снова, равны выигрыши.

Жесткий вызов. Сделайте тест, если вы действительно хотите знать, какой из них быстрее для вашего приложения.

1 голос
/ 16 июня 2011

Это будет зависеть от длины, содержания и количества ваших строк.

Если строк мало и они заполняются случайным образом, есть большая вероятность, что простое сравнение обнаружит несоответствие в пределах одного или двух символов, и будет проверяться только при полном совпадении содержимого. По сравнению с затратами на HashSet обслуживание и генерацию хеш-кода (полная строка каждый раз) я бы сделал ставку на простое сравнение.

Если строки могут быть похожими или более многочисленными, HashSet будет лучше.

[Обратите внимание, что ответы, предполагающие HashSet, будут быстрее игнорировать тот факт, что вы должны генерировать хеш-код для каждого добавления к HashSet, а не только для поиска. Этот факт не имеет значения, если ваши ссылочные строки не изменяются со временем.]

1 голос
/ 16 июня 2011

Есть только один способ убедиться - сопоставить его с реалистичными значениями.

0 голосов
/ 16 июня 2011

Если вы отсортируете строки и выполните бинарный поиск, то вы выполните максимум три compareTo теста. Если вы используете HashSet, вам нужно будет вычислить хэш для тестовой строки и выполнить хотя бы один тест equals (если он соответствует хеш-коду) или тест equals (для пропуска). Мне совсем не ясно, будет ли здесь большая разница, и фактическая производительность может зависеть от второстепенных вопросов, таких как уровень оптимизации.

Ответ, как всегда для такого рода вопросов, заключается в тестировании.

0 голосов
/ 16 июня 2011

HashSet не обязательно будет быстрее, но время будет постоянным . Цитирование из документации Java.

Этот класс предлагает постоянное время производительность для основных операций (добавить, удалить, содержит и размер)

Итак, если вы добавите больше строк для поиска значения, если вы используете равно, время будет относительно числа n строк, но с HashSet оно останется постоянным.

0 голосов
/ 16 июня 2011

С http://en.wikipedia.org/wiki/Java_hashCode%28%29#The_java.lang.String_hash_function

Начиная с Java 1.2, класс java.lang.String реализует свой hashCode () с использованием алгоритма суммы продуктов по всему тексту строки.

Дикие предположения здесь, но я не думаю, что будет большая разница, поскольку вычисление самого хеша примерно так же затратно, как и прямое сравнение строк, и вам, возможно, придется иметь дело со столкновениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...