Java 如何按字母顺序对字符串数组进行排序(不使用 compareTo 或 Arrays.sort)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18689672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 10:12:15  来源:igfitidea点击:

How to sort a String array alphabetically (without using compareTo or Arrays.sort)

javaarrayssorting

提问by Smilez221

I need to organize an array of Strings alphabetically. In theory, the first letter of each word is capitalized (although not necessarily, because one can't always trust users). I have tried Arrays.sort()and it won't run the program. I have tried using compareTo(), and while it runs the program, when it gets to that section of code, I get this error:

我需要按字母顺序组织一个字符串数组。理论上,每个单词的第一个字母都是大写的(虽然不一定,因为人们不能总是信任用户)。我试过了Arrays.sort(),它不会运行该程序。我尝试使用compareTo(),当它运行程序时,当它到达该代码部分时,我收到此错误:

Exception in thread "main" java.lang.NullPointerException
        at java.lang.String.compareTo(Unknown Source)
    at NameandAge.printNameOrder(NameandAge.java:431)
    at NameandAge.print(NameandAge.java:350)
    at NameandAge.main(NameandAge.java:116)

Literally everything I can find on this subject gives me one of those two solutions. Any other suggestions?

从字面上看,我可以在这个主题上找到的所有内容都为我提供了这两种解决方案之一。还有其他建议吗?

(For the record, the code currently reads: )

(为了记录,代码当前为:)

while(!done)
{
    done=true;   
    for(int i=0;i<organizedNames.length-1;i++)
    {
        if(!(organizednames[i]==null))
        {
            String name1=organizedNames[i]; String name2=organizedNames[i+1];
            if(name1!=null&&name2!=null)
            {
                int num=name1.compareTo(name2);
                if(num>0)
                { 
                    temp=organizedNames[i]; //temp is a String that was declared earlier
                    organizedNames[i]=organizedNames[i+1];
                    organizedNames[i+1]=temp;
                    done=false 
                }
            }
        }
    }
}

EDIT: Tried checking to make sure name1 and name2 weren't null. It works now, but this is the output: Joe
Bill
Bob
Smith
Rodney
James
Philip
Lillian
Charlie
Angel
Carol
Noah
I added the whole section of code now(minus the while loop, of course). This is basically the exact solution I found, and the first one to give me any output at all. What am I doing wrong?

编辑:尝试检查以确保 name1 和 name2 不是null。它现在可以工作了,但这是输出: Joe
Bill
Bob
Smith
Rodney
James
Philip
Lillian
Charlie
Angel
Carol
Noah
我现在添加了整个代码部分(当然,减去 while 循环)。这基本上是我找到的确切解决方案,也是第一个给我任何输出的解决方案。我究竟做错了什么?

EDIT (again): This is the code that calls the sort.

编辑(再次):这是调用排序的代码。

String[]organizedNames=new String[names.length];
organizedNames=sortNames(organizedNames);

And the code for the sort itself is basically what's in the answer below.

排序本身的代码基本上就是下面的答案。

回答by Zack Newsham

Assuming you are running some variation of the bubble sort algorithm, and that you have not sanitised you input array for null strings, the problem is likely that organizedNames[i]is null.

假设您正在运行冒泡排序算法的一些变体,并且您没有为空字符串清理输入数组,那么问题很可能organizedNames[i]是空值。

If this is the case you need to decide if you want to remove null items, or list them at the end of the array. If the latter is true, prior to doing a comparison, check if name1 == null || name2 == nullif so, set num to -1, this will put all the null items in an array in one place.

如果是这种情况,您需要决定是要删除空项目,还是将它们列在数组的末尾。如果后者为真,则在进行比较之前,检查是否为真,name1 == null || name2 == null将 num 设置为 -1,这会将数组中的所有空项放在一个位置。

To answer your secondary question, try this:

要回答您的次要问题,请尝试以下操作:

boolean done = false;
while(done == false){
  done = true;
  for(int i=0;i<organizedNames.length-1;i++)
  {
    int num = 0;
    if(organizedNames[i] != null && organizedNames[i + 1] != null)
    {
        String name1=organizedNames[i]; String name2=organizedNames[i+1];
        num=name1.compareTo(name2);
    }
    else if(organizedNames[i] == null && organizedNames[i + 1] == null){
      num = 0;
    }
    else if(organizedNames[i] == null){
      num = 1;
    }
    else {
      num = -1;
    }
    if(num>0)
    {
        String temp=organizedNames[i];
        organizedNames[i]=organizedNames[i+1];
        organizedNames[i+1]=temp;
        done=false;
    }
  }
}

回答by Stephen C

You've gotten yourself into a right mess here! What you've been trying to do is to implement your own sort algorithm from the ground up, without understanding why the original version wasn't working. It didn't work ... for the same reason the original version didn't work.

你已经把自己弄得一团糟!您一直在尝试做的是从头开始实现您自己的排序算法,而不理解为什么原始版本不起作用。它不起作用......出于同样的原因,原始版本不起作用。

If I am reading the evidence correctly, the root causeof your problems is the nullvalues in your input array. There are three simple ways to deal with this:

如果我正确阅读了证据,那么问题的根本原因null输入数组中的值。有三种简单的方法可以解决这个问题:

  1. Get rid of the nullvalues by creating a new (smaller) array with the nulls eliminated.

  2. Replace the nullvalues with some value (e.g. an empty String) that can be safely compared without causing an NPE.

  3. Implement a Comparatorthat is tolerant of nulls. For example, if we wanted to make nullsort after non-null strings ...

      public class MyComparator implements Comparator<String> {
          public int compare(String s1, String s2) {
              if (s1 == null) {
                  return (s2 == null) ? 0 : +1;
              } else {
                  return (s2 == null) ? -1 : s1.compareTo(s2);
              }
          }
      }
    
      String[] array = ...
      Arrays.sort(array, new MyComparator());
    
  1. 摆脱了null通过创建具有消除了空值的新的(较小的)阵列值。

  2. 将这些null值替换为一些String可以安全比较而不会导致 NPE 的值(例如空值)。

  3. 实现一个Comparator容忍nulls的a。例如,如果我们想null在非空字符串之后进行排序......

      public class MyComparator implements Comparator<String> {
          public int compare(String s1, String s2) {
              if (s1 == null) {
                  return (s2 == null) ? 0 : +1;
              } else {
                  return (s2 == null) ? -1 : s1.compareTo(s2);
              }
          }
      }
    
      String[] array = ...
      Arrays.sort(array, new MyComparator());
    

If you are interested in why your code in the Question isn't sorting properly, it is because of your strategy for dealing with null. Basically, the code (as written) compares successive pairs of array entries, swapping them if they are out of order. When it makes a pass through the array that doesn't find anything to swap, it stops. The problem is that if either of the elements it is comparing is null, it doesn't compare them. So if you have a nullin the array, any non-null elements before the nullcannot be compared with any non-null elements after the null.

如果您对问题中的代码排序不正确的原因感兴趣,那是因为您处理null. 基本上,代码(如编写的那样)比较连续的数组条目对,如果它们无序则交换它们。当它通过没有找到任何要交换的数组时,它会停止。问题是,如果它比较的任何一个元素是null,它就不会比较它们。因此,如果null数组中有 a ,null则不能将之前的任何非空元素与 之后的任何非空元素进行比较null

回答by srinivas gowda

Using collections we can do like this..

使用集合我们可以这样做..

SortedSet<String> set = new TreeSet<String>();
String[] s = { "this", "will", "be", "sorted", "without", "ba", "any", "sort()", "function", "or","comparator" };

        for (int i = 0; i < s.length; i++)
        {
            set.add(s[i]);
        }

        for (Object element : set) {
            System.out.println(element.toString());
        }

回答by 404 Brain Not Found

Firstly, String class is immutable, i.e. no matter how you sort it or arrange it. It will never change the insertion order inside itself.

首先,String 类是不可变的,即无论您如何对其进行排序或排列。它永远不会改变自身内部的插入顺序。

The reason for this is because when you create a String class object, a memory is allocated inside the String Constant/Literal Pool, which maybe be used by many other programs/methods that are concurrently running on the same JRE.

这样做的原因是因为当您创建一个 String 类对象时,会在 String Constant/Literal Pool 内部分配一块内存,这些内存可能会被同时运行在同一个 JRE 上的许多其他程序/方法使用。

 class Test{  
 public static void main(String args[]){  
   String s="Jake";  
   s.concat(" Paul");//concat() method appends the string at the end  
   System.out.println(s);//will print Jake because strings are immutable objects  
 }  
}  

Therefore, try the usual sorting algorithm wont work here.

因此,尝试通常的排序算法在这里不起作用。

You can how ever use StringBuilder instead of String. Since, StringBuilder is mutable, your manual sorting algorithms should work on them.

您可以使用 StringBuilder 而不是 String。由于 StringBuilder 是可变的,您的手动排序算法应该对它们起作用。

Hope this helps.

希望这可以帮助。

回答by Rishabh Rawat

Use this Code which not use any PredefinedArray.Sort()and compareTo()method

使用不使用任何预定义Array.Sort()方法的此代码compareTo()

sortStringArray(new String[]{"Henry Bernard",
            "Cherish Davidson",
            "Joshua Norris",
            "Eleanor Kelley",
            "Jaslyn Schneider",
            "Holly Herman",
            "Willie Strong",
            "Eliana Villa",
            "Lennon Odom",
            "Monica Velasquez",
            "Salvatore Levy",
            "Taliyah Bruce"});

public static void sortStringArray(String[] array) {
    for (int i = 0; i <= array.length - 1; i++) {
        for (int j = 1; j < array.length - i; j++) { //Apply the bubble Sort
            if (CompareString(array[j - 1], array[j]) == 1) { //Pass the two adjacent string for comparing
                String temp = array[j - 1];
                array[j - 1] = array[j];
                array[j] = temp;
            }
        }
    }

    for (int i = 0; i <= array.length - 1; i++) {
        System.out.println(array[i]);
    }
}

private static int CompareString(String first, String second) {
    int len;

    if (first.length() >= second.length()) //we need to take the smallest string length
        len = second.length();
    else
        len = first.length();

    for (int i = 0; i <= len; i++) {
        if (first.charAt(i) > second.charAt(i))  //Suppose the first string letters is greater then return 1; 
            return 1;
        else if (first.charAt(i) < second.charAt(i)) //if second string letter is greater then return -1;
            return -1;
    }
    return 0;  //if both the equal then return 0
}