[java] Why does my sorting loop seem to append an element where it shouldn't?

I am trying to sort an array of Strings using compareTo(). This is my code:

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

Now the output is:

Hello  This Example Sorting is

I am getting results, but not the results I want to get, which are:

Hello This Example Is Sorting

How can I adjust my code to sort the string array properly?

This question is related to java arrays sorting

The answer is


Apart from the alternative solutions that were posted here (which are correct), no one has actually answered your question by addressing what was wrong with your code.

It seems as though you were trying to implement a selection sort algorithm. I will not go into the details of how sorting works here, but I have included a few links for your reference =)

Your code was syntactically correct, but logically wrong. You were partially sorting your strings by only comparing each string with the strings that came after it. Here is a corrected version (I retained as much of your original code to illustrate what was "wrong" with it):

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

//Keeps track of the smallest string's 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;
     }
 }
}

Further Reading

The problem with this approach is that its asymptotic complexity is O(n^2). In simplified words, it gets very slow as the size of the array grows (approaches infinity). You may want to read about better ways to sort data, such as quicksort.


To begin with, your problem is that you use the method `compareTo() which is case sensitive. That means that the Capital letters are sorted apart from the lower case. The reason is that it translated in Unicode where the capital letters are presented with numbers which are less than the presented number of lower case. Thus you should use `compareToIgnoreCase()` as many also mentioned in previous posts.

This is my full example approach of how you can do it effecively

After you create an object of the Comparator you can pass it in this version of `sort()` which defined in java.util.Arrays.

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

take a close look at super. This makes sure that the array which is passed into is combatible with the type of comparator.

The magic part of this way is that you can easily sort the array of strings in Reverse order you can easily do by:

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)

Alternative Choice

The method compareToIgnoreCase(), although it works well with many occasions(just like compare string in english),it will wont work well with all languages and locations. This automatically makes it an unfit choice for use. To make sure that it will be suppoorted everywhere you should use compare() from java.text.Collator.

You can find a collator for your location by calling the method getInstance(). After that you should set this Collator's strength property. This can be done with the setStrength() method together with Collator.PRIMARY as parameter. With this alternative choise the IgnocaseComp can be written just like below. This version of code will generate the same output independently of the location

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

}

If you use:

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

you will get:

Example  Hello  is  Sorting  This

which I think is the output you were looking for.


Starting from Java 8, you can also use parallelSort which is useful if you have arrays containing a lot of elements.

Example:

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

If you want to ignore the case, you can use:

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

otherwise B will be before a.

If you want to ignore the trailing spaces during the comparison, you can use 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]
}

See:


I know this is a late reply but maybe it can help someone.

Removing whitespace can be done by using the trim() function. After that if you want to sort the array with case sensitive manner you can just use:

Arrays.sort(yourArray);

and for case insensitive manner:

Arrays.sort(yourArray,String.CASE_INSENSITIVE_ORDER);

Hope this helps!


Instead of this line

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

use this line

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

and you are good to go. The reason your current code is not working is explained by other users already. This above replacement is one workaround amongst several that you could apply.


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

First of all you provided spaces in " Hello " and " This ", spaces have a lower value than alphabetic characters in Unicode, so it gets printed first. (The rest of the characters were sorted alphabetically).

Now upper case letters have a lower value than lower case letter in Unicode, so "Example" and "Sorting" gets printed, then at last "is " which has the highest value.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to sorting

Sort Array of object by object field in Angular 6 Sorting a list with stream.sorted() in Java How to sort dates from Oldest to Newest in Excel? how to sort pandas dataframe from one column Reverse a comparator in Java 8 Find the unique values in a column and then sort them pandas groupby sort within groups pandas groupby sort descending order Efficiently sorting a numpy array in descending order? Swift: Sort array of objects alphabetically