Почему мой цикл сортировки, кажется, добавляет элемент, где он не должен?

Я пытаюсь отсортировать массив строк с помощью compareTo(). Это мой код:

static String Array[] = {" Hello ", " This ", "is ", "Sorting ", "Example"};
String temp;

public static void main(String[] args)
{

   for (int j=0; j<Array.length;j++)
   {
       for (int i=j+1 ; i<Array.length; i++)
       {
           if (Array[i].compareTo(Array[j])<0)
           {
               String temp = Array[j];
               Array[j] = Array[i];
               Array[i] = temp;
           }
       }
       System.out.print(Array[j]);
   }
}

Теперь вывод:

Hello  This Example Sorting is

Я получаю результаты, но не результаты, которые я хочу получить:

Hello This Example Is Sorting

Как настроить свой код для правильной сортировки массива строк?

Ответ 1

Ваш выход правильный. Обозначим белые символы "Hello" и "This" в начале.

Другая проблема связана с вашей методологией. Используйте метод Arrays.sort():

String[] strings = { " Hello ", " This ", "Is ", "Sorting ", "Example" };
Arrays.sort(strings);

Вывод:

 Hello
 This
Example
Is
Sorting

Здесь третий элемент массива "is" должен быть "Is", иначе он будет последним после сортировки. Поскольку метод сортировки внутренне использует значение ASCII для сортировки элементов.

Ответ 2

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

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

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

static  String Array[]={" Hello " , " This " , "is ", "Sorting ", "Example"};
String  temp;

//Keeps track of the smallest string index
int  shortestStringIndex; 

public static void main(String[] args)  
{              

 //I reduced the upper bound from Array.length to (Array.length - 1)
 for(int j=0; j < Array.length - 1;j++)
 {
     shortestStringIndex = j;

     for (int i=j+1 ; i<Array.length; i++)
     {
         //We keep track of the index to the smallest string
         if(Array[i].trim().compareTo(Array[shortestStringIndex].trim())<0)
         {
             shortestStringIndex = i;  
         }
     }
     //We only swap with the smallest string
     if(shortestStringIndex != j)
     {
         String temp = Array[j];
         Array[j] = Array[shortestStringIndex]; 
         Array[shortestStringIndex] = temp;
     }
 }
}

Дополнительная литература

Проблема с этим подходом заключается в том, что асимптотическая сложность O (n ^ 2). В упрощенных словах он становится очень медленным, так как размер массива растет (приближается к бесконечности). Вы можете прочитать лучшие способы сортировки данных, например quicksort.

Ответ 3

Вместо этой строки

if(Array[i].compareTo(Array[j])<0)

используйте эту строку

if(Array[i].trim().compareTo(Array[j].trim())<0)

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

Ответ 4

Я знаю, что это поздний ответ, но, возможно, он может помочь кому-то.

Удаление пробелов может быть выполнено с помощью функции trim(). После этого, если вы хотите отсортировать массив с чувствительным к регистру образом, вы можете просто использовать:

Arrays.sort(yourArray);

и для нечувствительности к регистру:

Arrays.sort(yourArray,String.CASE_INSENSITIVE_ORDER);

Надеюсь, это поможет!

Ответ 5

Начиная с Java 8, вы также можете использовать parallelSort, что полезно, если у вас есть массивы, содержащие много элементов.

Пример:

public static void main(String[] args) {
    String[] strings = { "x", "a", "c", "b", "y" };
    Arrays.parallelSort(strings);
    System.out.println(Arrays.toString(strings));   // [a, b, c, x, y]
}

Если вы хотите игнорировать случай, вы можете использовать:

public static void main(String[] args) {
    String[] strings = { "x", "a", "c", "B", "y" };
    Arrays.parallelSort(strings, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {              
            return o1.compareToIgnoreCase(o2);
        }
    });
    System.out.println(Arrays.toString(strings));   // [a, B, c, x, y]
}

иначе B будет до a.

Если вы хотите игнорировать конечные пробелы во время сравнения, вы можете использовать trim():

public static void main(String[] args) {
    String[] strings = { "x", "  a", "c ", " b", "y" };
    Arrays.parallelSort(strings, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {              
            return o1.trim().compareTo(o2.trim());
        }
    });
    System.out.println(Arrays.toString(strings)); // [  a,  b, c , x, y]
}

См

Ответ 6

" Hello " , " This " , "is ", "Sorting ", "Example"

Прежде всего, вы предоставили пробелы в " Hello " и " This ", пробелы имеют меньшее значение, чем алфавитные символы в Юникоде, поэтому он сначала печатается. (Остальные символы были отсортированы в алфавитном порядке).

Теперь буквы верхнего регистра имеют меньшее значение, чем строчная буква в Юникоде, поэтому печатаются "Пример" и "Сортировка", а затем "is ", который имеет самое высокое значение.

Ответ 7

Если вы используете:

if (Array[i].compareToIgnoreCase(Array[j]) < 0)

вы получите:

Example  Hello  is  Sorting  This

который, я думаю, является результатом, который вы искали.

Ответ 8

Во-первых, ваша проблема заключается в том, что вы используете метод compareTo(), чувствительный к регистру. Это означает, что прописные буквы сортируются отдельно от нижнего регистра. Причина в том, что он переводится в Юникоде, где заглавные буквы представлены числами, которые меньше, чем представленное число нижнего регистра. Таким образом, вы должны использовать `compareToIgnoreCase()`, как многие из них упоминаются в предыдущих сообщениях.

Это мой полный пример подхода, как вы можете сделать это эффективно

После создания объекта Компаратор вы можете передать его в этой версии `sort()`, которая определена в java.util.Arrays.

static<T>void sort(T[]array,Comparator<?super T>comp)

внимательно посмотрите на super. Это гарантирует, что массив, который передается, совместим с типом компаратора.

Магическая часть этого способа состоит в том, что вы можете легко отсортировать массив строк в Обратном порядке, с помощью которого вы можете легко:

return strB.compareToIgnoreCase(strA);

import java.util.Comparator;

    public class IgnoreCaseComp implements Comparator<String> {

        @Override
        public int compare(String strA, String strB) {
            return strA.compareToIgnoreCase(strB);
        }

    }

  import java.util.Arrays;

    public class IgnoreCaseSort {

        public static void main(String[] args) {
            String strs[] = {" Hello ", " This ", "is ", "Sorting ", "Example"};
            System.out.print("Initial order: ");

            for (String s : strs) {
                System.out.print(s + " ");
            }

            System.out.println("\n");

            IgnoreCaseComp icc = new IgnoreCaseComp();

            Arrays.sort(strs, icc);

            System.out.print("Case-insesitive sorted order:  ");
            for (String s : strs) {
                System.out.print(s + " ");
            }

            System.out.println("\n");

            Arrays.sort(strs);

            System.out.print("Default, case-sensitive sorted order: ");
            for (String s : strs) {
                System.out.print(s + " ");
            }

            System.out.println("\n");
        }

    }

 run:
    Initial order:  Hello   This  is  Sorting  Example 

    Case-insesitive sorted order:   Hello   This  Example is  Sorting  

    Default, case-sensitive sorted order:  Hello   This  Example Sorting  is  

    BUILD SUCCESSFUL (total time: 0 seconds)

Альтернативный выбор

Метод compareToIgnoreCase(), хотя он работает хорошо во многих случаях (так же, как и сравнение строки на английском языке), он не будет хорошо работать со всеми языками и местоположениями. Это автоматически делает его непригодным для использования. Чтобы убедиться, что он будет поддерживаться везде, вы должны использовать compare() из java.text.Collator.

Вы можете найти коллактор для своего местоположения, вызвав метод getInstance(). После этого вы должны установить свойство прочности Collator. Это можно сделать с помощью метода setStrength() вместе с Collator.PRIMARY в качестве параметра. С помощью этого альтернативного варианта IgnocaseComp можно написать так, как показано ниже. Эта версия кода будет генерировать один и тот же вывод независимо от местоположения

import java.text.Collator;
import java.util.Comparator;

//this comparator uses one Collator to determine 
//the right sort usage with no sensitive type 
//of the 2 given strings
public class IgnoreCaseComp implements Comparator<String> {

    Collator col;

    IgnoreCaseComp() {
        //default locale
        col = Collator.getInstance();

        //this will consider only PRIMARY difference ("a" vs "b")
        col.setStrength(Collator.PRIMARY);
    }

    @Override
    public int compare(String strA, String strB) {
        return col.compare(strA, strB);
    }

}