Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Быстрый способ сравнить строки 
:(
    Опции темы
DenWPF
Дата 21.9.2010, 14:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1659
Регистрация: 26.9.2009

Репутация: нет
Всего: 1



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

equals - он как сравнивает по символьно?



PM MAIL   Вверх
Joil
Дата 21.9.2010, 15:03 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 24.1.2008

Репутация: нет
Всего: 8



Цитата(DenWPF @  21.9.2010,  14:27 Найти цитируемый пост)
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;
    }

--------------------
Who had deceived thee so often as thyself? © Benjamin Franklin--------------------Always bear in mind that your own resolution to succeed is more important than any other. © Abraham Lincoln--------------------If you need it - do it, if you want it - take it! © ...
PM MAIL ICQ   Вверх
DenWPF
Дата 21.9.2010, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1659
Регистрация: 26.9.2009

Репутация: нет
Всего: 1



по символьный, значит быстрей уже не как. ну гуд. спасибо.
PM MAIL   Вверх
Joil
Дата 21.9.2010, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 211
Регистрация: 24.1.2008

Репутация: нет
Всего: 8



Цитата(DenWPF @  21.9.2010,  15:15 Найти цитируемый пост)
по символьный, значит быстрей уже не как. ну гуд. спасибо. 

Ну почему, если строки очень большие то я думаю быстрее будет взять хэш от каждой строки и сравнить хэши.
--------------------
Who had deceived thee so often as thyself? © Benjamin Franklin--------------------Always bear in mind that your own resolution to succeed is more important than any other. © Abraham Lincoln--------------------If you need it - do it, if you want it - take it! © ...
PM MAIL ICQ   Вверх
DenWPF
Дата 21.9.2010, 18:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1659
Регистрация: 26.9.2009

Репутация: нет
Всего: 1



а как хэш генерируется?
PM MAIL   Вверх
jk1
Дата 21.9.2010, 19:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Код

myString.hashCode();



--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
DenWPF
Дата 21.9.2010, 20:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1659
Регистрация: 26.9.2009

Репутация: нет
Всего: 1



ну я в плане механизме.
PM MAIL   Вверх
jk1
Дата 21.9.2010, 21:37 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1168
Регистрация: 17.10.2008
Где: Санкт-Петербург

Репутация: 40
Всего: 75



Цитата

ну я в плане механизме. 

Код

 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;
    }


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

Это сообщение отредактировал(а) jk1 - 21.9.2010, 21:41


--------------------
Opinions are like assholes — everybody has one
PM MAIL   Вверх
Skipy
Дата 22.9.2010, 09:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 487
Регистрация: 24.8.2006
Где: Москва, Россия

Репутация: 6
Всего: 16



Цитата(Joil @ 21.9.2010,  18:27)
Ну почему, если строки очень большие то я думаю быстрее будет взять хэш от каждой строки и сравнить хэши.

У неравных строк могут быть равные хеши, это не противоречит контракту. Обратное неверно. Так что НЕравенство выяснить можно по хеш-коду. Но если они равны - это ни о чем не говорит. То же верно и про хеш-функции (хотя попасть в 128 бит того же MD5 намного сложнее, чем в 32 бита hashCode). Кстати, подсчет хеша займет порядочно времени, имхо, сравнить быстрее.

Можно, конечно, попользоваться методом intern. Но во-первых, это надо делать аккуратно, во-вторых, одно сравнение все-таки будет (когда в буфере строку будут искать), в-третьих - при интенсивном использовании рискуете получить OutOfMemory:PermGen - буфер сильно разрастется.


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
danilka
Дата 22.9.2010, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 15.1.2010

Репутация: нет
Всего: нет



Цитата(Skipy @  22.9.2010,  09:50 Найти цитируемый пост)
Можно, конечно, попользоваться методом intern. Но во-первых, это надо делать аккуратно, во-вторых, одно сравнение все-таки будет (когда в буфере строку будут искать), в-третьих - при интенсивном использовании рискуете получить OutOfMemory:PermGen - буфер сильно разрастется. 


А вот об этом можно поподробнее?
Почему это надо делать аккуратно?
Разве строка будет искаться в буфере когда для нее нужен intern(). Там нет прямой ссылки?
Если не пользоваться intern() разве буфер не разрастется?

PM MAIL   Вверх
Skipy
Дата 22.9.2010, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 487
Регистрация: 24.8.2006
Где: Москва, Россия

Репутация: 6
Всего: 16



Цитата
Почему это надо делать аккуратно?


Потому что как только Вы начнете сравнивать строки через == - Вам ВЕЗДЕ надо будет использовать intern. Очень легко это забыть. Плюс есть строки, которые создаются не Вами, их тоже придется обрабатывать.

Цитата
Разве строка будет искаться в буфере когда для нее нужен intern(). Там нет прямой ссылки?


Какой ссылки? Вы себе представляете, как работает intern? Почитайте документацию: http://download.oracle.com/javase/6/docs/a...g.html#intern()

Цитата
When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned.


as determined by the equals(Object) method означает, что для определения наличия в пуле вызывается equals. Более того, происходит ПОИСК, что означает как минимум несколько сравнений, даже при оптимизациях. Таким образом, на каждый вызов intern как минимум один раз equals вызовется. А скорее всего - больше одного раза. И с ростом размера пула возможен рост времени поиска.

Цитата
Если не пользоваться intern() разве буфер не разрастется?


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


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
danilka
Дата 22.9.2010, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 15.1.2010

Репутация: нет
Всего: нет



Цитата(Skipy @  22.9.2010,  12:52 Найти цитируемый пост)
Потому что как только Вы начнете сравнивать строки через == - Вам ВЕЗДЕ надо будет использовать intern. Очень легко это забыть. Плюс есть строки, которые создаются не Вами, их тоже придется обрабатывать.


Нет ну понятно что я везде не буду использовать такое сравнение...

Цитата(Skipy @  22.9.2010,  12:52 Найти цитируемый пост)
Какой ссылки? Вы себе представляете, как работает intern? Почитайте документацию: http://download.oracle.com/javase/6/docs/a...g.html#intern()


Просто у меня был мысль что после того как у строки вызван метод intern() и соответствующий инстанс в пуле найден, почему бы в строке не сохранить ссылку на него...


Цитата(Skipy @  22.9.2010,  12:52 Найти цитируемый пост)
А с чего бы ему разрастаться? В буфер попадают строковые литералы и результаты вызова intern. Если не пользоваться intern - там будут только строковые литералы. Ну и если кто-то другой кладет строки через intern - они тоже, но на это Вы никак не влияете.


Мне почему-то казалось что строковые литералы и результаты вызова intern() это одно и тоже.
PM MAIL   Вверх
Skipy
Дата 22.9.2010, 16:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 487
Регистрация: 24.8.2006
Где: Москва, Россия

Репутация: 6
Всего: 16



Цитата
Нет ну понятно что я везде не буду использовать такое сравнение...


Вот именно. Тогда в каждом месте, где Вы будете использовать ==, необходимо будет обеспечить наличие intern-ированной строки. Т.е. ОЧЕНЬ аккуратно отслеживать, где у Вас строки из пула, а где нет. Это сложно.

Цитата
Просто у меня был мысль что после того как у строки вызван метод intern() и соответствующий инстанс в пуле найден, почему бы в строке не сохранить ссылку на него...


В какой строке? У Вас есть объект - String. Он содержит массив char-ов, длину строки и смещение в массиве. Всё. Никаких ссылок на intern-строки он не содержит и содержать не может. Потому как в общем случае в пуле аналогичной строки нет. 

Цитата
Мне почему-то казалось что строковые литералы и результаты вызова intern() это одно и тоже.


Вам казалось. Строковые литералы - это те строки, которые Вы в коде описываете как "строка". Каждый такой объект преобразуется в String и помещается в пул.

Код

package test;

public class Class1 {

    public static String getString(){
        return "test string";
    }

}


Код

package test;

public class Class2 {

    public static String getString(){
        return "test string";
    }

}


Код

package test;

public class Test {

    public static void main(String[] args) {
        System.out.println(Class1.getString() == Class2.getString());
    }

}


Вот этот тест вернет true. Но к intern это не имеет никакого отношения, этот метод тут, как видите, не вызывается. Всё делается на стадии компиляции и загрузки классов.


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
danilka
Дата 22.9.2010, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 15.1.2010

Репутация: нет
Всего: нет



Цитата(Skipy @  22.9.2010,  16:43 Найти цитируемый пост)
В какой строке? У Вас есть объект - String. Он содержит массив char-ов, длину строки и смещение в массиве. Всё. Никаких ссылок на intern-строки он не содержит и содержать не может. Потому как в общем случае в пуле аналогичной строки нет. 


Под строкой я и имел ввиду объект класса String. То есть Вы хотите сказать что можно создать строку так чтобы в пуле не было соответствующего ей объекта intern()?

Поделитесь первоисточником плиз где описано как хранятся строковые литералы, и пул для intern-строк и в какой момент они заполняются.


PM MAIL   Вверх
Evgeni68
Дата 24.9.2010, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 9.7.2007

Репутация: 2
Всего: 3



Цитата(danilka @ 22.9.2010,  17:46)
То есть Вы хотите сказать что можно создать строку так чтобы в пуле не было соответствующего ей объекта intern()?

Код

String test = new String("Hello world");


Данный код создаст объект типа String не помещая строку в пул.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0887 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.