Какой самый быстрый способ сравнить строки в Java? - PullRequest
27 голосов
/ 27 сентября 2010

Как быстрее всего сравнить две строки в Java?

Есть ли что-то быстрее, чем равно?

EDIT: Я не могу помочь, чтобы прояснить проблему.

У меня есть две строки, которые отсортированы в алфавитном порядке и точно такой же размер

Пример: abbcee и abcdee

Строки могут быть длиной до 30 символов

Ответы [ 7 ]

32 голосов
/ 27 сентября 2010

Я не ожидаю, что Sun Oracle еще не оптимизировал стандарт String#equals() до максимума. Итак, я ожидаю, что это будет уже самый быстрый путь. Загляните немного в его источник, если вы хотите узнать, как они это реализовали. Вот выдержка:

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;
}
25 голосов
/ 24 марта 2012

Сравнить строки одинаковой длины быстрее, используя хэш-код:

public static boolean equals(final String s1, final String s2) {
return s1 != null && s2 != null && s1.hashCode() == s2.hashCode()
    && s1.equals(s2);
}

Вы можете проверить это, мои результаты для 4000000 операций сравнения, включая идентичные, равные и разные строки:

String.equals(String):  177081939
equals(String, String):  44153608

Примечание: Вычисление hashCode нового строкового объекта занимает некоторое время вычисления, после чего hashCode сохраняется в объекте.Поэтому мое предложенное улучшение будет быстрее, чем сравнение по умолчанию, если строковые объекты используются повторно.В моем приложении я использую строковые константы и храню строки в коллекциях.Множественное сравнение строк с использованием моего метода на самом деле быстрее для меня, но в целом это может быть не так.

Если метод все время используется с новыми строками, такими как compare("a", "b"), это не будет улучшением.

Таким образом, самый быстрый способ сравнения строк зависит от:

  • Повторно ли используются ваши строковые объекты (например, из коллекции) или всегда новые (например,из входного потока)
  • Независимо от длины строк
  • Отличаются ли строки в начале или конце строки
  • Ваш стиль программирования, сколько константused
  • Ваше использование String.intern ()

Игнорируя эти факты, большинство всех программ будут в порядке с String.equals ().

4 голосов
/ 07 октября 2014

Я пробовал разные комбинации для сравнения строк ( код здесь ):

1. s1.equals(s2)
2. s1.length() == s2.length() && s1.hashCode() == s2.hashCode() && s1.equals(s2)
3. s1.hashCode() == s2.hashCode() && s1.equals(s2);
4. s1.length() == s2.length() && s1.equals(s2);

Я использовал строки длиной 40 символов, в итерациях 10000000000L и перед любой итерацией я заново инициализировал строки.

за равные укусы я получил:

equal: 2873 milis ???
equal: 21386 milis
equal: 7181 milis
equal: 2710 milis ???

для строк того же размера, но последний разный символ, который я получил:

different: 3011 milis
different: 23415 milis
different: 6924 milis
different: 2791 milis

для разных размеров, почти одинаковые строки, но в конце добавлен один символ для s2:

different size: 3167 milis
different size: 5188 milis
different size: 6902 milis
different size: 2951 milis

мне кажется, что лучше использовать сначала сравнение string.length (), прежде чем equals ().

Но это почти не будет иметь значения, потому что это тот случай, когда у меня есть 10 ^ 10 строк сравнения с длиной 40 символов, и что странно для меня, это случай, когда для равных строк у меня лучше скорость при сравнении Длина строки первая.

3 голосов
/ 28 сентября 2010

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

s1.hashCode() == s2.hashCode() && s1.equals(s2)

Это может быть немного быстрее. Возможно, нет.

3 голосов
/ 27 сентября 2010

Зависит от того, что вам нужно.Я думаю, что equals () действительно оптимизирован, но, возможно, вам нужно что-то еще быстрее, чем equals ().Взгляните на этот пост .

1 голос
/ 27 февраля 2015

Простой ответ

String.equals(Object)

Я почти уверен ( в этом ответе есть несколько ссылок ), и вполне вероятно, что JIT будет иметь встроенную для String#equals, что означает, что он сможет заменить вызов специально созданным машинный код для архитектуры, на которой в данный момент работает JVM.

0 голосов
/ 27 сентября 2010

Как всегда, вам понадобится тест для вашего приложения / среды. И если вы уже не профилировали и не представили это как узкое место в производительности, это, вероятно, не имеет значения («преждевременная оптимизация - корень всех зол»).

Сказав это:

a.equals (b) это очень быстро для строк. Вероятно, это один из наиболее тщательно оптимизированных фрагментов кода на платформе Java. Я был бы очень удивлен, если бы вы могли найти более быстрый способ сравнения двух произвольных строк.

Есть особые случаи , где вы можете обмануть и безопасно использовать (a == b) , например, если вы знаете, что обе строки интернированы (и, следовательно, значение идентичности подразумевает идентичность объекта). В этом случае это может быть немного быстрее, чем a.equals (b) - но опять же это зависит от реализации компилятора / JVM. И очень легко выстрелить себе в ногу, если ты не знаешь, что делаешь .....

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