Сравнение строк: индивидуальное сравнение и сравнение добавленной строки - PullRequest
2 голосов
/ 06 января 2009

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

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

Комбинации, которые я должен проверить, это str11 - str12 - str13 как одна группа и str21 - st2222 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 ) {

        }

    }

}

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

Ответы [ 8 ]

10 голосов
/ 06 января 2009

Я проверю индивидуально.

Является ли «AB», «CD», «EF» равным «ABC», «DE», «F»?

Я так не думаю.

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

8 голосов
/ 06 января 2009

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

if (  str11 equals str21
   && str12 equals str22
   && str13 equals str23) ...
3 голосов
/ 07 января 2009

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

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

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

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

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

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

1 голос
/ 13 января 2009

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

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

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

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

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

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

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

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

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

1 голос
/ 06 января 2009

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

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

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

1 голос
/ 06 января 2009

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

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

0 голосов
/ 06 января 2009

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

Я бы не беспокоился о расходах на производительность. Просто напишите это наиболее читаемым способом. Компилятор 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);
0 голосов
/ 06 января 2009

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

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

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

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