學校但願根據同專業的同窗們的績點平均分班
,你須要打印出每一個班級的全部學生信息
。java
能夠把這個問題分解成如下幾個小任務:git
建立一個名爲
Student
的類,包含:github
姓名(建立
Name
的類)數組
- 考慮
名
、中間名
、姓
- 學號:整型
加權平均績點(建立
Grade
類並利用Arraylist
實現)this
- 採用北京交通大學的五級九段制,詳情請點擊連接:
北京交通大學本科生課程考覈與成績管理辦法建立一個名爲
ClassInfo
的類,包含:spa
- 收集全部學生的我的信息,利用
Arraylist
實現- 對收集到的學生信息用
冒泡排序法
從新排序基於班級個數,用
"S"型排序
從新分班ssr
什麼是"S"型排序呢?rest
- 假設總共有三個班級,4位學生。咱們將績點由低到高的順序,將第一位給1班,第二位給2班。若是班級人數不能整除學生人數也不要緊,後面的排序方式依然由低到高,直到排完爲止。如示意圖所示:
![]()
- 經過績點(調用
Arraylist
的方法)找到對應的學生信息- 打印各班學生信息
Name
類代碼以下:code
/** * @author Hephaest * @version 6/04/2018 * @since jdk1.8.0_162 */ public class Name { //聲明實例變量 private String first; private String second; private String last; private String fullName; /**初始化構造方法,用 this 指向類中的實例變量,尤爲是當調用的參數和內部聲明參數一致時*/ //當沒有中間名時 public Name(String first, String last) { this.first = first; this.last = last; } //當有中間名時 public Name(String first, String second, String last) { this.first = first; this.second = second; this.last = last; } //判斷是否有中間名,有的話注意是兩個空格 public String getFullName() { if(second==null) { fullName=first+" "+last; return fullName; } else { fullName=first+" "+second+" "+last; return fullName; } } }
Grade
類代碼以下:orm
/** * @author Hephaest * @version 6/04/2018 * @since jdk1.8.0_162 */ import java.util.*; public class Grade { private String rank; private double grade; private double xuefen; /** * 若是成績是以等級形式給的,使用這個構造方法 * @param rank 等級 * @param xuefen 學分 */ public Grade(String rank,double xuefen) { this.rank=rank; this.xuefen=xuefen; this.grade=0.0; } /** * 若是成績是以百分比或者直接就是績點的形式,使用這個構造方法 * @param grade 百分比的成績或績點 * @param xuefen 學分 */ public Grade(double grade,double xuefen) { this.grade=grade; this.xuefen=xuefen; this.rank=""; } /* 考慮成績是以哪一種形式輸入的,進入對應的判斷語句 * 判斷標準詳見:http://www.bjtu.edu.cn/pub/xxgk/xxgksxqs/xsglfwxx/18999.htm */ public double getgrade() { if(rank.equalsIgnoreCase("")) { if(grade>100||grade<0) { System.out.println("Wrong input!"); grade=0.0; xuefen=0.0; return grade; } else if (grade>=96) { grade=5.0; return grade; } else if (grade>=91) { grade=4.5; return grade; } else if (grade>=86) { grade=4.0; return grade; } else if (grade>=81) { grade=3.5; return grade; } else if (grade>=76) { grade=3.0; return grade; } else if (grade>=71) { grade=2.5; return grade; } else if (grade>=66) { grade=2.0; return grade; } else if (grade>=61) { grade=1.5; return grade; } else if (grade>=60) { grade=1.0; return grade; } else if(grade>=00&&grade<=5) { return grade; } else { grade=0.0; return grade; } } else { //由於輸入的是一串字符串,因此要轉換成一個個字符 char[] array= rank.toCharArray(); double grade=0.0; for(int i=0;i<array.length;i++) { switch(array[i]) { case 'A': grade=4.0; break; case 'B': grade=3.0; break; case 'C': grade=2.0; break; case 'D': grade=1.0; break; case 'F': grade=0.0; break; case '+': grade+=0.5; break; case '-': if(grade<=0) { break; } else { grade-=0.5; break; } default: System.out.println("Your input is wrong!"); } } return grade; } } public double getXuefen() { return xuefen; } }
Student
類代碼以下:
/** * @author Hephaest * @version 6/04/2018 * @since jdk1.8.0_162 */ import java.text.DecimalFormat; import java.util.ArrayList; public class Student { //用Name聲明實例變量name,用ArrayList<grade> 聲明grade private Name name; private int id; private ArrayList<Grade> grade; //若是沒有中間名,使用這個構造方法進行實例化 public Student(String first, String last, int id) { this.name = new Name(first, last);//調用以前寫好的Name類 this.id = id; grade=new ArrayList<Grade>();//調用已經在package有的Arraylist類 } //若是有中間名,使用這個構造方法進行實例化 public Student(String first, String second, String last, int id) { this.name = new Name(first, second, last); this.id = id; grade=new ArrayList<Grade>(); } //直接獲取Name裏的方法,避免重寫 public String getName() { return name.getFullName(); } //一個學生可能有不少項成績,鏈表的add方法就是在(單個)學生的成績後面繼續追加成績,很實用的辦法 public void addGrade(Grade newGrade) { grade.add(newGrade); } //把一個學生的全部成績進行加權平均運算,獲得最終的績點 public double averageGPA() { double sum1=0.0; double sum2=0.0; for(int i = 0;i < grade.size(); i++) { sum1+=grade.get(i).getgrade()*grade.get(i).getXuefen(); sum2+=grade.get(i).getXuefen(); } return sum1/sum2; } //獲取學生學號 public int getID() { return id; } //對單個學生的全部信息進行打印,依次爲:姓名-學號-平均績點 public void print() { DecimalFormat fm = new DecimalFormat("#.##"); System.out.println("Name:\t " + getName() + "\nID:\t " + getID() + "\nGPA:\t" + fm.format(averageGPA())); } }
ClassInfo
類代碼以下:
/** * @author Hephaest * @version 6/04/2018 * @since jdk1.8.0_162 */ import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; public class ClassInfo { private ArrayList<Student> students; // 用 Arraylist 聲明students public ClassInfo() { students =new ArrayList<Student>(); } /** * initialInfo 用來獲取控制檯中輸入的全部學生信息 * @param numberOfStudent 肯定輸入學生的個數 * @param newclas 輸入創造的對象 */ public void initialInfo(int numberOfStudent,Object newclas) { Scanner info=new Scanner (System.in); ClassInfo newclass=(ClassInfo)newclas; for(int i=0;i<numberOfStudent;i++) { System.out.println("Set the student's ID number:"); int number=info.nextInt(); System.out.println("Set the student's first name:"); String space = info.nextLine(); String first=info.nextLine(); System.out.println("Does student has second name?"); String answer=info.nextLine(); if(answer.equalsIgnoreCase("y")) { System.out.println("Set the student's second name:"); String second=info.nextLine(); System.out.println("Set the student's last name:"); String last=info.nextLine(); newclass.addStudent(new Student(first,second,last,number)); } else { System.out.println("Set the student's last name:"); String last=info.nextLine(); newclass.addStudent(new Student(first,last,number)); } System.out.println("Which types of grades you want to input:\n"+ "\t1:rank\n"+ "\t2:score\n"); int choice=info.nextInt(); switch(choice) { case 1: System.out.println("Set the student's rank:"); space = info.nextLine(); String rank=info.nextLine(); System.out.println("Set the student's xuefen:"); double xuefen=info.nextDouble(); newclass.addNewRank(i,new Grade(rank,xuefen)); break; case 2: System.out.println("Set the student's score"); double score=info.nextDouble(); System.out.println("Set the student's xuefen"); double fen=info.nextDouble(); newclass.addNewScore(i,new Grade(score,fen)); break; } boolean flag=true; while(flag==true) { System.out.println("Does any grade need to be added?"); space = info.nextLine(); answer=info.nextLine(); switch(answer) { case "Y": case "y": System.out.println("Which types of grades you"+ "want to input:\n"+ "\t1:rank\n"+ "\t2:score\n"); choice=info.nextInt(); space = info.nextLine(); switch(choice) { case 1: System.out.println("Set the student's rank"); String rank=info.nextLine(); System.out.println("Set the student's xuefen"); double xuefen=info.nextDouble(); newclass.addNewRank(i,new Grade(rank,xuefen)); break; case 2: System.out.println("Set the student's score"); double score=info.nextDouble(); System.out.println("Set the student's xuefen"); double fen=info.nextDouble(); newclass.addNewScore(i,new Grade(score,fen)); break; } break; case "n": case "N": flag=false; break; default: System.out.println("Please answer \"yes\" or \"no\" !"); } } } } //students裏追加學生(包括每一個學生的全部信息) public void addStudent(Student newStudent) { students.add(newStudent); } /** * 這個方法實現每位學生能夠擁有多個成績,經過追加的方法 * @param index 表明學生鏈表中第幾位學生 * @param newGrade grade對象(建立新的成績) */ public void addNewScore(int index,Grade newGrade) { students.get(index).addGrade(newGrade); } /* * 本質上與上面的方法同樣,名字不一樣爲了好區分新輸入的成績的形式 */ public void addNewRank(int index,Grade newGrade) { students.get(index).addGrade(newGrade); } /* * 這裏使用泡沫排序法對學生的成績進行排序 * 由於沒有辦法爲Arraylist建立數組 * 所以用新的數組拷貝students裏全部的成績 * 注意:數組下表和students的下表並非意義對應的關係 */ public double[] bubbleSortStudent() { double temp; int size = students.size(); double[] array=new double[size]; for (int i=0;i<size;i++) { array[i]=students.get(i).averageGPA(); } for(int i = 0 ; i < size-1; i ++) { for(int j = 0 ;j < size-1-i ; j++) { if(array[j] > array[j+1]) { temp = array[j]; array[j] = array[j+1]; array[j+1] = temp; } } } return array; } /** * 通過上面一步,咱們成功把students裏全部學生的成績拷貝給數組array[i] ** 如今咱們要作的就是根據學生的成績分配到不一樣的班級 * 經常使用的方法是「S」型排法 * @param num 班級的總數 * @param array 泡沫排序完後的數組 * @return 分班完後的二維數組結果 */ public double[][] allocateStudent(int num,double[] array) { int classNum=students.size()/num; int classrest=students.size()%num; classNum+=classrest; double[][] arr=new double[num][classNum]; int k; for(int j=0;j<num;j++) { k=j; for(int i=0;i<classNum;i++) { if(k>=students.size()) { break; } else { arr[j][i]=array[k]; k+=num; } } } return arr; } //找到須要刪除的學生所在的students下標,調用remove方法便可 public void removeStudent(int studentEntry) { students.remove(studentEntry); } /** * 打印每一個班級的學生信息 * @param num 班級的總數 * @param arr 通過「S」型排列完的二維數組(可看做已經分班完的結果) * 調用的是 allocateStudent 方法裏返回的數組 * 注意:通常在公佈分班狀況的時候不會顯示個體的成績(確保隱私權) * 這裏體現是爲了驗證分班結果的正確性 */ public void print(int num,double[][]arr) { for(int i=0;i<arr[0].length;i++) { System.out.println("Class"+(i+1)+" list:"+"\n"); System.out.println("--------------------"); for(int j=0;j<arr.length;j++) { for(int k=0;k<students.size();k++) { if(arr[i][j]==students.get(k).averageGPA()) { students.get(k).print(); System.out.println("\n"); removeStudent(k); } } } } } //主方法 public static void main(String [] args) { ClassInfo newclass=new ClassInfo(); Scanner info=new Scanner (System.in); System.out.println("Set the number of students:"); int numberOfStudent=info.nextInt(); newclass.initialInfo(numberOfStudent,newclass); System.out.println("Set the number of classes:"); int number=info.nextInt(); newclass.print(number,newclass.allocateStudent(number,newclass.bubbleSortStudent())); info.close(); } }
輸出結果:
Set the number of students: 3 Set the student's ID number: 20181201 Set the student's first name: William Does student has second name? y Set the student's second name: Jefferson Set the student's last name: Smith Which types of grades you want to input: 1:rank 2:score 1 Set the student's rank: A+ Set the student's xuefen: 6 Does any grade need to be added? Y Which types of grades you want to input: 1:rank 2:score 2 Set the student's score 88 Set the student's xuefen 5 Does any grade need to be added? N Set the student's ID number: 20181145 Set the student's first name: James Does student has second name? n Set the student's last name: Bush Which types of grades you want to input: 1:rank 2:score 1 Set the student's rank: B+ Set the student's xuefen: 5 Does any grade need to be added? n Set the student's ID number: 20181219 Set the student's first name: Mary Does student has second name? n Set the student's last name: Clinton Which types of grades you want to input: 1:rank 2:score 1 Set the student's rank: C Set the student's xuefen: 2 Does any grade need to be added? n Set the number of classes: 2 Class1 list: -------------------- Name: Mary Clinton ID: 20181219 GPA: 2 Name: William Jefferson Smith ID: 20181201 GPA: 4.27 Class2 list: -------------------- Name: James Bush ID: 20181145 GPA: 3.5
寫這篇博客有感於看到的一個知乎問題:一個學校分班的問題,使用Java若是實現?
我把問題簡化了,主要利用Arraylist能夠追加對象的辦法,把全部須要的信息都封裝在對象裏,以達到分配和後續更改的目的。固然,個人代碼並無處理異常狀況以及輸入錯誤的提示(太懶)。面向對象的好處是當須要處理大量複雜個個體時能比較有效的更改所需的個體信息,這個代碼還能夠繼續完善:好比容許更改學生姓名、繼續追加單個學生的成績等等。
Github 源碼