用Java按字母顺序排列学生数组

问题描述:

我目前有这个程序读取文本文件的内容,并计算平均值和采取的测试分数量,并将它们整齐地打印在小数据表中。这些名字,取测验的数量和平均每个学生的:用Java按字母顺序排列学生数组

James Tiberius Kirk    8       91.63 
Buffy Summers     7       83.14 
Tom Baker      15      100.00 
Malcolm Reynolds     9       84.22 
Elizabeth Bennet     9       93.33 
John Blutarsky     9       0.00 
Dorthy Gale      6       85.83 

所有这些Student S的存储命名Anames[]阵列内。我想知道是否可以根据这些学生按字母顺序用姓氏使用我现在拥有的代码来排序。当我运行它,它给我的错误:

异常线程“main” java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:-1

at java.lang.String.substring(String.java:1927) 
at text.reader.TextReader.compareLastNames(TextReader.java:117) 
at text.reader.TextReader.main(TextReader.java:94) 

这里是我的主类的代码:

public static void main(String[] args)throws IOException{ 

    Double score=0.0; 
    int b,j; 
    String tempfirst = ""; 
    String templast = ""; 
    Student Anames[] = new Student[30]; 
    Student Temp[] = new Student [1]; 
    int Stucount = 0; 
    Scanner reader = new Scanner(new File("quizScores.txt")); 
    boolean runProgram = true; 
    PrintWriter writer = new PrintWriter(new File("scoreReport.txt")); 
    //prints header for report 
    System.out.println("Name      Number Quizes    Quiz Socres"); 
    writer.println("Name      Number Quizes    Quiz Socres"); 

    //check to see if end of file string 
    while (!reader.hasNext("-10")){ 
     String name="", first="", last=""; 

     //gets the name from file 
     while(!reader.hasNextDouble()){ 
      last = reader.next(); 

      while (!reader.hasNextDouble()){ 
       first = first+reader.next()+" "; 
      } 
      name=first+last; 
     } 

     //creates new student with given name 
     Student newStudent = new Student(first, last); 
     Anames[Stucount] = newStudent; 
     Stucount++; 

     //gets the quiz scores and makes sure does not averge in the end of file string. 
     while (reader.hasNextDouble()&& !reader.hasNext("-10")){ 
      newStudent.addQuiz(reader.nextDouble()); 
     } 

     //Prints out the formated data 
     System.out.printf("%-30s%4.0f%30.2f \n",newStudent.getName(), newStudent.getQuizNumber(), newStudent.getAverage()); 
     writer.printf("%-30s%4.0f%30.2f",newStudent.getName(), newStudent.getQuizNumber(), newStudent.getAverage()); 

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

    for (b = 0; b < Stucount; b++){ 
     int INTEGERTEMP = b; 
     for (j= b+1; j < Stucount; j++){ 
      int INTEGERTEMP2 = j; 
      if ((compareLastNames(Anames[INTEGERTEMP].getLAST(), Anames[INTEGERTEMP2].getLAST()))>0){ 
       Temp[0] = Anames[b]; 
       Anames[b] = Anames[j]; 
       Anames[j] = Temp[0]; 
      } 
     } 
    } 

    System.out.println("Name      Number Quizes    Quiz Socres"); 
    for (int i = 0; i < Stucount; i++) { 

      System.out.printf("%-30s%4.0f%30.2f \n", Anames[i].getName(), Anames[i].getQuizNumber(), Anames[i].getAverage()); 

    } 

    writer.close(); 
} 

private static int compareLastNames(String a, String b){ 
    int index_a = a.lastIndexOf(" "); 
    String surname_a = a.substring(index_a); 
    int index_b = b.lastIndexOf(" "); 
    String surname_b = b.substring(index_b); 
    int lastNameCmp = surname_a.compareToIgnoreCase(surname_b); 
    return lastNameCmp; 
} 

这里是包含大部分的方法中使用的Student.java:

public Student (String inName, String inLast){ 
    studentName=inName; 
    studentLast = inLast; 
    quizAverage = 0; 
    quizScore=0; 
    numberQuizes=0; 
} 

public void addQuiz(double inQuiz){ 
    quizScore += inQuiz; 
    numberQuizes++; 
} 

public double getAverage(){ 
    quizAverage = quizScore/numberQuizes; 
    return quizAverage; 
} 

public String getName(){ 
    return studentName+studentLast; 
} 

public double getQuizNumber(){ 
    return numberQuizes; 
} 

public String getLAST(){ 
    return studentLast; 
} 
+0

看来你的程序会认为姓氏是James,Buffy,Tom,Malcolm,Elizabeth,John和Dorthy。 (或者我可能会感到困惑,看起来你并没有真正使用'last'和'first'变量来表示最后名字和第一个名字,但是这部分代码很混乱。) – ajb

+1

为什么不使用a定制比较器?这样你不需要创建自己的compareLastnames方法 – AbtPst

+0

你的文件的确切格式是什么?另外,为什么不让'学生'执行'可比较的'? –

您可以使用java.util.Arrays.sort(Student [] arr, Comparator<Student> comp)而不是您自己的比较代码。在单行中,您可以像这样实现:

Student arr[];//considering this array you will populate 
Arrays.sort(arr,new java.util.Comparator<Student>(){ 

      public int compare(Student o1, Student o2) { 

       return o1.studentLast.compareTo(o2.studentLast); 
      } 

     }); 
//then the arr will be sorted with studentLast name 
+0

谢谢汤姆。我试着将你的代码输入到我的主类中,我面临的唯一问题是它告诉我它需要一个.class类时需要一个值吗?我是否将它插入错误的区域? –

+0

@ J.Z你接受的实际例外是什么? – ptierno

+0

@ptierno异常在线程“主”java.lang.RuntimeException:不可编译的源代码 - 错误的树型: \t at text.reader.TevaReader.main(TextReader.java:88) –

让我们从异常中找回问题,找出问题出在哪里。首先,它告诉我们在117线上有StringIndexOutOfBoundsException;也就是说,行

String surname_a = a.substring(index_a); 

你会从异常通知消息(它实际上可能是surname_b行,你已经从意味着我不能匹配正确的行类中删除代码)有用地告诉我们使用的索引是-1。我们来看看为什么a.lastIndexOf(" ");会返回-1。我们在documentation for String中看到,当字符不在字符串中时,它返回-1。

现在,让我们再回到异常的堆栈跟踪中,找出为什么该字符串中没有空格。异常告诉我们检查94行,我们看到

if ((compareLastNames(Anames[INTEGERTEMP].getLAST(), Anames[INTEGERTEMP2].getLAST()))>0){ 

那么,这是怎么回事?我们将每个学生的姓氏(以及姓氏)传递给我们的比较函数。姓氏的大部分都没有空格。

那么,我们该如何解决这个问题呢?那么,如果实际上有一个空格,即你返回的索引不是-1,那么你必须改变你的函数只接受姓氏的子字符串。

一旦你完成了比较功能,我建议你看看how to write an Object that implements the Comparable interface。这将允许您使用库排序功能,这将比您自己的排序功能更快,更没有问题(最有可能!)。