Что такое строка лексикографически? Ява

Метод compareTo() в Java сравнивает две строки «лексикографически». Может кто-нибудь просто объяснить, как работает лексикографическое сравнение в Java?

Я нашел этот пост, в котором объясняются три случая ‹0 , ==0 и >0 ; Однако я все еще в замешательстве...

Означает ли это, что возвращаемое int — это количество мест, в которых строки находятся друг от друга, если их нужно отсортировать в алфавитном порядке, как в словаре?

Кроме того, как метод справляется с чувствительностью к регистру? Являются ли строчные буквы первыми в строке перед прописными? Есть ли график для этого?

Например, приведенный ниже код выдает -31. Означает ли это, что строка Dog отстоит от строки cat на -31 позицию?

public static void main(String[] args) {
     Scanner keyboard = new Scanner(System.in);   

     String str1 = "Dog";

     String str2 = "cat";

     int result = str1.compareTo(str2);
     System.out.println(result);

person B537B7725DC58715F6E6BFA7AFC20C    schedule 16.09.2015    source источник
comment
Вы можете прочитать исходный код здесь: docjar.com/html/api /java/lang/String.java.html   -  person PeterMmm    schedule 16.09.2015
comment
Возвращаемое значение очень хорошо документировано в классе String.   -  person Dmitry Zaytsev    schedule 16.09.2015


Ответы (2)


Возвращаемое значение на самом деле не имеет значения, поскольку контракт compareTo должен возвращать отрицательное, положительное значение или 0 (как вы уже знаете).

Однако, если вы действительно хотите понять, почему -31 возвращается при сравнении Dog с cat (или любой другой строкой), вы можете просто посмотреть на метод непосредственно в классе String:

public int compareTo(String anotherString) {
    int len1 = value.length;
    int len2 = anotherString.value.length;
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;

    int k = 0;
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}

Имейте в виду, что value — это массив char, поддерживающий строку.

private final char value[];

Так как же работает этот метод?

  • Вы получаете минимальную длину обеих строк в переменной lim.
  • Вы создаете копию массива строковых символов.
  • Вы перебираете каждый символ (проверяя, равны ли они), пока не достигнете нижнего предела.
  • Если два символа с одинаковым индексом не равны, вы возвращаете результат вычитания второго из первого. char может быть представлено как значение int (которое принимает значение ascii) и уже упорядочено. Таким образом, при вычитании будет возвращено отрицательное число, если второй символ «больше», чем первый. Положительный результат будет возвращен, если второй символ "ниже", чем первый. 0 будет возвращено, если оба равны.
  • Если все символы были равны во время цикла для наименьшей длины строки, вы возвращаете вычитание обеих длин.

В вашем примере первая буква обоих слов не равна, поэтому вы можете сравнить D с c, которые соответственно представлены как 68 и 99. Вычтите 99 из 68, и вы получите -31.

Итак, чтобы ответить на этот вопрос:

Означает ли это, что возвращаемое int — это количество мест, в которых строки находятся друг от друга, если их нужно отсортировать в алфавитном порядке, как в словаре?

Нет, на самом деле это либо разница между двумя несовпадающими значениями ascii char, либо разница обеих длин.

Кроме того, как метод справляется с чувствительностью к регистру? Являются ли строчные буквы первыми в строке перед прописными? Есть ли график для этого?

Если вы хотите игнорировать регистр при сравнении, вы можете использовать String#compareToIgnoreCase.

Также вы можете проверить эту диаграмму для значений ascii (верхний и нижний регистр).

person Jean-François Savard    schedule 16.09.2015
comment
Очень хороший ответ, Жан, спасибо. Мне нравится, как вы объяснили код метода построчно. Единственный вопрос, который у меня есть сейчас: как получилось, что разница только в первых символах? 68-99 = -31. Разве он не должен продолжать сравнивать остальные символы, такие как «o» с «a» и «g» с «t»? - person B537B7725DC58715F6E6BFA7AFC20C; 16.09.2015
comment
@JonathanScialpi Нет, нет смысла сравнивать остальную часть строки. Нам просто нужно проверить разницу между первым символом, не прошедшим проверку на равенство, поскольку это единственный символ, который имеет значение при упорядочении строки в алфавитном порядке. - person Jean-François Savard; 16.09.2015

Я нашел Определение лексикографического порядка в Википедии очень полезным при ответе на ваш вопрос.

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

возьмите список слов:

  • Кот
  • собака
  • животное
  • трубкозуб

Если мы сравним их, мы возьмем первый символ каждого и посмотрим. Когда мы сравниваем «кошку» и «собаку», мы берем первые буквы «с» и «d» и сравниваем их. Численно в коде простой (не обязательно лучший) способ сделать это - преобразовать их в числовое значение и вычесть одно значение из другого. Это будет равно 0, если они одинаковы, и мы перейдем к сравнению следующего символа в каждом. Если они разные, то мы знаем, что один лексикографически (по алфавиту) следует за другим.

Возвращаемое значение не требуется для предоставления какой-либо полезной информации. Вот почему единственные значения, которые что-то значат, это ‹0 , ==0 и >0.

Что касается корпуса, это деталь реализации. Существуют компараторы, которые будут считать верхний регистр «А» таким же, как нижний регистр «а», а есть компараторы, которые этого не делают, поскольку они имеют разные числовые значения. . (См.: Как сортировать по алфавиту, игнорируя регистр? ).

person Kylar    schedule 16.09.2015