为什么我的排序循环似乎附加了一个不应该的元素?

时间:2012-10-20 07:40:01

标签: java arrays sorting

我正在尝试使用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

如何调整代码以正确排序字符串数组?

8 个答案:

答案 0 :(得分:146)

您的输出是正确的。在开头用“Hello”和“This”表示白色字符。

另一个问题是您的方法。使用Arrays.sort()方法:

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

<强>输出:

 Hello
 This
Example
Is
Sorting

这里数组“is”的第三个元素应该是“Is”,否则它将在排序后进入最后。因为sort方法在内部使用ASCII值对元素进行排序。

答案 1 :(得分:15)

除了这里发布的替代解决方案(这是正确的)之外,没有人通过解决您的代码错误来回答您的问题。

好像您正在尝试实施selection sort算法。我不会详细介绍排序的工作原理,但我已经提供了一些链接供您参考=)

您的代码在语法上是正确的,但在逻辑上是错误的。您只是将每个字符串与其后面的字符串进行比较,从而对字符串进行了部分排序。这是一个更正后的版本(我保留了原始代码,以说明它的“错误”):

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

进一步阅读

这种方法的问题在于它的asymptotic complexity is O(n^2)。简而言之,随着阵列大小的增加(接近无穷大),它变得非常慢。您可能需要阅读better ways to sort data,例如quicksort

答案 2 :(得分:9)

而不是这一行

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

使用此行

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

你很高兴。其他用户已经解释了当前代码无法正常工作的原因。以上替换是您可以应用的几种解决方法之一。

答案 3 :(得分:9)

我知道这是一个迟到的回复,但也许它可以帮助某人。

可以使用trim()函数删除空格。 之后,如果您想以区分大小写的方式对数组进行排序,您可以使用:

Arrays.sort(yourArray);

以及不区分大小写的方式:

Arrays.sort(yourArray,String.CASE_INSENSITIVE_ORDER);

希望这有帮助!

答案 4 :(得分: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]
}

查看

答案 5 :(得分:4)

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

首先,您在" Hello "" This "中提供了空格,空格的值低于Unicode中的字母字符,因此首先打印。 (其余字符按字母顺序排序)。

现在,大写字母的值低于Unicode中的小写字母,因此打印“示例”和“排序”,然后打印最后值为"is "的值。

答案 6 :(得分:4)

如果您使用:

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

你会得到:

Example  Hello  is  Sorting  This

我认为是您正在寻找的输出。

答案 7 :(得分:2)

首先,您的问题是您使用区分大小写的`compareTo()方法。这意味着大写字母与小写字母分开。原因是它在Unicode中翻译,其中大写字母以小于所呈现的小写字母的数字表示。因此,你应该使用`compareToIgnoreCase()`,就像之前的帖子中提到的那样。

这是我如何有效地做到这一点的完整示例方法

创建 Comparator 的对象后,可以将此版本的`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(),虽然它适用于很多场合(就像英语中的比较字符串一样),但它不适用于所有语言和位置。这会自动使其成为不合适的选择。为了确保在任何地方都支持它,您应该使用 java.text.Collat​​or 中的compare()

您可以通过调用方法getInstance()找到您所在位置的整理器。之后你应该设置这个Collat​​or的强度属性。这可以使用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);
    }

}