Сравнение строк: индивидуальное сравнение и сравнение добавленных строк

У меня есть шесть строковых переменных: str11, str12, str13, str21, str21 и str23.

Мне нужно сравнить комбинацию этих переменных.

Комбинации, которые мне нужно проверить, это str11 - str12 - str13 как одна группа и str21 - str22 - str23 как другая группа. Я должен сравнить эти две группы.

Теперь я в замешательстве, какой метод мне использовать для сравнения?

Могу ли я добавить строки из той же группы и сравнить, это только одно сравнение сказать ( str11 append str12 append str13 ) eqauls ( str21 append str22 append str23 )

Или же

Стоит ли мне делать 3 индивидуальных сравнения?

if ( str11 equals str21 ) {

    if ( str12 equals str22 ) {

        if ( str13 equals str23 ) {

        }

    }

}

Какой коэффициент производительности стоит мне из-за длины строки при сравнении строк? Предположим, что все строки имеют одинаковую (приблизительную) длину.

Почему вы беспокоитесь о производительности здесь? Сравнение - узкое место?

orip 06.01.2009 17:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
1 194
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Разделение сравнения на три оператора if определенно не требуется. Вы также можете просто выполнить И с вашими сравнениями, например

if (  str11 equals str21
   && str12 equals str22
   && str13 equals str23) ...

Сложить строки вместе и сравнить не получится. Например, строки 1 и 2 могут быть пустыми, а строка 3 может содержать «gorps», в то время как строка 4 содержит «gorps», а 5 и 6 - пустыми. Сравнение добавленных результатов вернет истину, хотя это будет ложноположительным. Вам нужно будет придумать разделитель, который, как вы гарантируете, не будет содержаться ни в какой строке, чтобы заставить это работать, и это может стать беспорядочным.

Я бы просто сравнил так, как вы это делаете. Он читабельный и простой.

@Tom Значит, я гарантировал разделитель?

pramodc84 06.01.2009 16:36

Если вы решите добавить разделитель, то вы увеличиваете стоимость конкатенации строк (у вас есть n-1 дополнительных конкатенаций для n строк)

Binary Worrier 06.01.2009 16:38

Если у вас есть гарантированный разделитель, эта схема будет работать, но конкатенация строк предполагает создание дополнительных строковых объектов. Как я уже сказал, я бы сделал индивидуальные сравнения. Другой способ сработает, но будет более дорогостоящим.

Tom Moseley 06.01.2009 16:42

@Binary - я знаю. Я представил это как единственное условие, при котором подход concat будет работать. Как я уже сказал, я бы применил метод индивидуального сравнения.

Tom Moseley 06.01.2009 16:43

@Tom: Я слышал тебя, это было скорее предупреждением для читателя, я понял из твоего ответа, хотя это была плохая идея. Удачи, чувак :)

Binary Worrier 06.01.2009 17:08

я бы использовал простой способ

динамический прогон по всем элементам обоих массивов.

            boolean isEqual = true;
            for(int n = 0;n<str1.length;++n){
                isEqual &= str1[n].equals(str2[n]);
            }

            return isEqual;

Я не думаю, что это скомпилирует.

Grant Wagner 06.01.2009 17:07

-1 чрезмерно спроектирован, не оптимизирован (большое n и str1 [0] не равно str2 [0])

eljenso 06.01.2009 18:19
Ответ принят как подходящий

Я буду тестировать индивидуально.

«AB» «CD» «EF» равно «ABC» «DE» «F»?

Мне кажется, что нет.

P.S. Если это так, то это ОЧЕНЬ частный случай, и если вы решите закодировать его таким образом (как конкатенированное сравнение), то прокомментируйте его к черту.

Итерация по одной большой char [], вероятно, быстрее, чем итерация по n отдельным строкам общей одинаковой длины. Это связано с тем, что данные очень локальны, и ЦП легко может выполнить предварительную выборку данных.

Однако, когда вы объединяете несколько строк в Java, вы будете использовать StringBuilder / Buffer, а затем преобразовать i обратно в String в нескольких случаях. Это приведет к увеличению выделения памяти из-за того, как работает SB.append () и неизменяемость Java String, что, в свою очередь, может создать узкое место в памяти и значительно замедлить работу вашего приложения.

Я бы рекомендовал оставить строки как есть и провести отдельное сравнение. Прирост производительности из-за более длинного char [], скорее всего, намного меньше, чем проблемы, с которыми вы можете столкнуться с более высокой скоростью распределения.

Я бы сложил две группы в два массива, а затем перебрал бы массивы, чтобы сравнить отдельные строки в этом массиве. Хороший пример уже есть в анклаве, приведенный Маркусом Лаусбергом.

Я бы не беспокоился о затратах на производительность. Просто напишите это как можно более читабельным способом. Компилятор Java очень хорош в оптимизации производительности.

Пример метода:

    public boolean compareGroups(String[] group1, String[] group2){
    if (group1.length != group2.length ){
        return false;
    }

    for (int i = 0; i < group1.length; i++) {
        if (!group1[i].equals(group2[i])){
            return false;
        }
    }

    return true;
}

И вызвать метод, конечно же, просто:

        String[] group1 = new String[]{"String 1", "String 2", "String 3"};
    String[] group2 = new String[]{"String 1", "String 2", "String 3"};

    boolean result = compareGroups(group1, group2);

@ Рольф Да, конечно. Я не меняю существующий вопрос. Это еще один вопрос, если я не ошибаюсь

pramodc84 06.01.2009 17:44

Имена ваших переменных указывают на сильный запах кода. Похоже, что вместо шести переменных у вас должно быть два массива, каждый из которых содержит три строки. Другими словами, изначально было бы намного лучше что-то вроде этого:

String[][] strs = new String[2][3];
strs[0][0] = str11;
strs[0][1] = str12;
...

Скорее всего, в зависимости от того, откуда вы получили шесть строк, вам не нужно будет делать это вручную непосредственно перед сравнением, но, скорее всего, вы можете передать свои аргументы в более удобном формате.

Если вы действительно хотите сделать это путем сравнения массивов строковых объектов и используете Java 1.5 или выше, помните, что у вас есть доступ к методам java.util.Arrays.equals () для проверки равенства массивов. Максимально возможное использование библиотечных методов - отличный способ избежать лишних усилий, связанных с изобретением велосипеда, и возможных ошибок реализации (например, обе представленные реализации содержат ошибки).

Точный маршрут, который вы выберете, вероятно, зависит от домена, для которого вы пишете - если ваша конкретная проблема требует, чтобы вы всегда сравнивали 3-кортежи, то написание кода для явного сравнения групп из трех строк не было бы такой хорошей идеей, как это было бы вероятно, будет более понятным, чем код, сравнивающий массивы произвольной длины. (Если вы идете по этому пути, то непременно используйте одно условное выражение if () с && вместо вложенных блоков if, как продемонстрировал Адам Беллер).

Однако в целом у вас будет гораздо более повторно используемый блок кода, если вы настроите его для работы с массивами произвольной длины.

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

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

Но что меня больше всего поражает:

3) Мне это кажется типичным случаем «преждевременной оптимизации» и подсчета циклов процессора не в том месте.

Если вы действительно заботитесь о производительности, забудьте о стоимости трех отдельных сравнений по сравнению с одним сравнением. Вместо:

Как насчет дополнительных накладных расходов на создание двух конкатенированных строк?

  (str11 + str12 + str13) = (str21 + str22 + str23)

Давайте проанализируем, что w.r.t. диспетчеру памяти и операциям, которые необходимо выполнить. На низком уровне это переводит 4 дополнительных выделения памяти, 2 дополнительных strcpy и либо еще 4 дополнительных strcat или strcpy (в зависимости от того, как это делает виртуальная машина; но большинство из них будет использовать другую strcpy) операции. Затем вызывается единственное сравнение, при котором сначала не производится подсчет символов с помощью strlen; вместо этого он либо заранее знает размер (если заголовок объекта также включает количество символов, что вероятно), либо просто достигает 0-байта. Это называется один раз против трех. Фактическое количество символов для сравнения примерно одинаково (забудьте о лишних 0-байтах). Это оставляет нам 2 дополнительных вызова strcmp (несколько нс) по сравнению с накладными расходами, которые я описал выше (несколько мкс). Если мы сложим накладные расходы на восстановление GC (0 выделений против 4), я бы сказал, что ваше «оптимизированное» решение может легко быть в 100–1000 раз медленнее, чем 3 strcmps!

Дополнительное уведомление:
Теоретически JITter мог бы оптимизировать его или его часть и фактически сгенерировать код, как это было предложено Адамом Беллером, но я сомневаюсь, что какой-либо JIT-разработчик позаботится об оптимизации такого кода. Между прочим, строковые процедуры системы (также известные как строковые операции) обычно НАМНОГО быстрее, чем ручное кодирование, поэтому не начинайте самостоятельно перебирать отдельные символы.

Другие вопросы по теме