【问题标题】:How to sort a String array alphabetically (without using compareTo or Arrays.sort)如何按字母顺序对字符串数组进行排序(不使用 compareTo 或 Arrays.sort)
【发布时间】:2013-09-12 10:28:55
【问题描述】:

我需要按字母顺序组织一个字符串数组。理论上,每个单词的第一个字母都是大写的(虽然不一定,因为不能总是信任用户)。我试过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)

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

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

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

编辑:尝试检查以确保 name1 和 name2 不是 null。它现在可以工作,但这是输出: 乔
比尔
鲍勃
史密斯
罗德尼
詹姆斯
菲利普
莉莲
查理
天使
卡罗尔
诺亚
我现在添加了整个代码部分(当然,减去了 while 循环)。这基本上是我找到的确切解决方案,也是第一个给我任何输出的解决方案。我究竟做错了什么?

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

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

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

【问题讨论】:

  • 没有看到NameandAge源代码,没有人能回答你。
  • 你为什么不实际发布while循环的所有代码,这样我们就可以看到你的问题出在哪里。我怀疑问题是如果一对中的一个项目为空,你什么都不做,而你想要做的是当你找到一个空值时将 num 设置为 -1,当你找到时设置为 +1另一个为空。
  • 考虑完成。但不确定它有什么帮助。

标签: java arrays sorting


【解决方案1】:

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

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

要回答你的第二个问题,试试这个:

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

【讨论】:

  • 我做了(如编辑所示),只是不像你建议的那样。无论如何都要试试,以防万一。
  • 自从我在Java中工作以来已经有一段时间了,事实证明,如果任何一个String为空,你就会得到一个错误。所以对organizedNames[i + 1] 执行相同的检查。我编辑了我的回复以显示这一点。
  • 我尝试了你的第二个建议,得到了和以前一样的输出。
  • 你要排序的数组的初始值是多少?
  • 我不完全确定您的意思,但这是我对您要问的问题的回答:初始值是输出中的名称,按此顺序,后跟一个一堆nulls。这可能完全没有帮助。能具体一点吗?
【解决方案2】:

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

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

  1. 通过创建一个新的(较小的)数组来消除 null 值并消除空值。

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

  3. 实现一个容忍nulls 的Comparator。例如,如果我们想让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());
    

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      这样做的原因是,当您创建一个 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  
       }  
      }  
      

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

      您可以使用 StringBuilder 代替 String。由于 StringBuilder 是可变的,因此您的手动排序算法应该适用于它们。

      希望这会有所帮助。

      【讨论】:

        【解决方案5】:

        使用不使用任何预定义的代码 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
        }
        

        【讨论】:

          猜你喜欢
          • 2020-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-04
          • 1970-01-01
          • 2012-03-16
          • 1970-01-01
          相关资源
          最近更新 更多