---
tags: Cmoney_Java題目
---
Java_Cmoney_Week2_介面練習
===

1.需要的 Class
---
1.1 產生隨機資料的(隨機字串與隨機數字)
---
將裡面的方法都用成靜態,這樣使用時就不用 new 出實體。
```java=
package com.company;
/** 產生隨機資料用
*
*/
public class Input {
/** 隨機產生從 min~max 長度的字串,字串由隨機的 26個英文小寫字母組成
* @param hint 跑出的提示
* @param min 隨機字串最小長度
* @param max 隨機字串最大長度
* @return String 回傳隨機字串
*/
public static String randomInputString(String hint, int min, int max) {
System.out.print(hint + ": ");
StringBuilder str = new StringBuilder();
for (int i = 0; i < Input.random(min, max); i++) {
str.append((char) Input.random(97, 122));
}
System.out.println(str);
return str.toString();
}
/** 隨機產生從 min~max 範圍的數字
* @param hint 跑出的提示
* @param min 隨機數字最小值
* @param max 隨機數字最大值
* @return int 隨機數字
*/
public static int randomInputNum(String hint,int min, int max) {
System.out.print(hint + ": ");
int randomNum = random(min,max);
System.out.println(randomNum);
return randomNum;
}
/** 隨機產生從 min~max 範圍的數字
* @param min 隨機數字最小值
* @param max 隨機數字最大值
* @return int 隨機數字
*/
public static int random(int min, int max) {
return (int) (Math.random() * (max - min + 1) + min);
}
}
```
1.2 學生
---
如果屬性都是必填的話,用建造者模式會有點多餘。
```java=
package com.company;
/**
* 產生學生物件用
*/
public class Student {
private int seat;
private int score;
private String name;
/**
* InnerBuilder
*
* @param builder
*/
private Student(Builder builder) {
setSeat(builder.seat);
setScore(builder.score);
setName(builder.name);
}
public static final class Builder {
private int seat;
private int score;
private String name;
public Builder() {
}
public Builder setSeat(int val) {
seat = val;
return this;
}
public Builder setScore(int val) {
score = val;
return this;
}
public Builder setName(String val) {
name = val;
return this;
}
public Student build() {
return new Student(this);
}
}
// Getter and Setter
public int getSeat() {
return seat;
}
public void setSeat(int seat) {
this.seat = seat;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 輸出學生物件的樣子
@Override
public String toString() {
return "座號: " + seat +
" 成績: " + score +
" 姓名: " + name;
}
}
```
1.3 學生陣列物件
---
1. 創建比較器介面再到主程式使用匿名類別
2. 創建篩選器介面再到主程式使用匿名類別
```java=
package com.company;
/** 創造學生陣列用,用來儲存學生物件
*
*/
public class StudentArray {
private Student[] arr;
private int count;
/** 比較器介面
*
*/
public interface Comparator {
public int compare(Student s1, Student s2);
}
/** 篩選器介面
*
*/
public interface Filter {
public boolean filter(Student student);
}
/**
* 建構子
*/
public StudentArray() {
this.arr = new Student[2];
this.count = 0;
}
/** 將學生物件加到學生陣列的最後一個
* @param student 要加入的學生物件
*/
public void add(Student student) {
// 如果加入為 null
if (student == null) {
return;
}
// 如果加入時,學生陣列已經滿了,需要增加空間
if (this.count == this.arr.length) {
doubleArr();
}
// 將學生物件加到學生陣列中
this.arr[count++] = student;
}
/** 使用 index 找到該位置的學生,並回傳此學生物件
* @param index 要找的位置
* @return Student 回傳學生物件
*/
public Student getStudentByIndex(int index) {
// 如果 index < 0 或大於現有的學生物件數量,則回傳 null
if (index < 0 || index >= count) {
return null;
}
// 回傳該位置的學生物件
return this.arr[index];
}
/** 使用篩選器找到符合條件的學生,加到一個暫時的 StudentArray ,並回傳 StudentArray
* @param filter 使用的篩選器
* @return StudentArray 回傳 StudentArray
*/
public StudentArray where(Filter filter) {
// 創建一個暫時的學生陣列
StudentArray tmpArr = new StudentArray();
// 將符合篩選器的學生加入到暫時的學生陣列
for (int i = 0; i < this.count; i++) {
Student tmpStudent = this.arr[i];
if (filter.filter(tmpStudent)) {
tmpArr.add(tmpStudent);
}
}
return tmpArr;
}
/** 使用比較器排序,並回傳 StudentArray
* @param c 使用的比較器
* @return StudentArray 回傳 StudentArray
*/
public StudentArray sort(Comparator c) {
// 創建一個暫時的學生陣列
StudentArray tmpArr = new StudentArray();
// 將遠本的學生陣列深度拷貝到暫時的學生陣列
for (int i = 0; i < this.count; i++) {
tmpArr.add(this.arr[i]);
}
// 將暫時的學生陣列進行泡沫排序
for (int i = 0; i < this.count - 1; i++) {
for (int j = 0; j < this.count - i - 1; j++) {
if (c.compare(tmpArr.getStudentByIndex(j), tmpArr.getStudentByIndex(j + 1)) > 0) {
tmpArr.swap(j, j + 1);
}
}
}
return tmpArr;
}
/** 回傳現在有幾個學生
* @return int 學生數量
*/
public int length() {
return this.count;
}
/** 將學生陣列空間乘以兩倍,並將東西轉移到新陣列
*
*/
private void doubleArr() {
// 創建一個暫時的學生陣列
Student[] tmpArr = new Student[arr.length * 2];
// 將遠本的學生陣列深度拷貝到暫時的學生陣列
for (int i = 0; i < arr.length; i++) {
tmpArr[i] = this.arr[i];
}
this.arr = tmpArr;
}
/** 將學生陣列的兩個學生物件互換位置
* @param i1
* @param i2
*/
private void swap(int i1, int i2) {
Student tmp = this.arr[i1];
this.arr[i1] = this.arr[i2];
this.arr[i2] = tmp;
}
// Getter and Setter
public Student[] getArr() {
return arr;
}
public void setArr(Student[] arr) {
this.arr = arr;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
```
2.主程式
---
```java=
package com.company;
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 學生資料庫物件
StudentArray studentArray = new StudentArray();
// 讓使用者持續輸入
while (true) {
System.out.println("請輸入功能");
// 讓使用者輸入功能編號
int opt = sc.nextInt();
// 吃掉上面的換行符號
sc.nextLine();
switch (opt) {
// 新增一名學生到學生陣列,使用 Input 自動產生座號、成績、姓名
case 1:
studentArray.add(new Student.Builder()
.setSeat(Input.randomInputNum("自動產生座號: ", 1, 100))
.setScore(Input.randomInputNum("自動產生成績: ", 0, 100))
.setName(Input.randomInputString("自動產生姓名: ", 2, 3))
.build()
);
break;
// 排序學生陣列
case 2:
System.out.println("請輸入排序方法編號: 1.依照座號 2.依照成績 3.依照姓名 ");
// 讓使用者輸入篩選規則編號
int sortFuncNum = sc.nextInt();
// 吃掉上面的換行符號
sc.nextLine();
// 排序學生陣列(依據剛才的選擇編號 sortFuncNum)
sortFunc(studentArray, sortFuncNum);
// 印出學生陣列內所有學生物件
printAllStu(studentArray);
break;
case 3:
// 隨機排序學生陣列
randomSequence(studentArray);
// 印出學生陣列內所有學生物件
printAllStu(studentArray);
break;
case 4:
// 印出學生陣列內所有學生物件
printAllStu(studentArray);
break;
case 5:
// 離開系統
System.exit(0);
break;
}
}
}
/** 印出學生陣列內所有學生物件
* @param studentArray
*/
public static void printAllStu(StudentArray studentArray) {
// 迴圈掃過學生陣列內所有物件並印出
for (int i = 0; i < studentArray.getCount(); i++) {
System.out.println(studentArray.getStudentByIndex(i));
}
// 分隔線
System.out.println("--------------------------------");
}
/** 排序學生陣列的各種方法
* @param studentArray 要排序的學生陣列
* @param sortFuncNum 要選擇排序的規則
*/
public static void sortFunc(StudentArray studentArray, int sortFuncNum) {
// 創建一個暫時的學生陣列
StudentArray result;
// 看輸入哪個規則編號決定排序方式
switch (sortFuncNum) {
// 使用座號排列(由小到大)
case 1:
// 將排序後的學生陣列放到暫時的學生陣列
result = studentArray.sort((s1, s2) -> s1.getSeat() - s2.getSeat());
// 將原本的學生陣列設置成暫時的學生陣列(排好的)
studentArray.setArr(result.getArr());
break;
// 使用成績排列(由小到大)
case 2:
// 將排序後的學生陣列放到暫時的學生陣列
result = studentArray.sort(((s1, s2) -> s1.getScore() - s2.getScore()));
// 將原本的學生陣列設置成暫時的學生陣列(排好的)
studentArray.setArr(result.getArr());
break;
// 使用姓名排列(由a到z)
case 3:
// 將排序後的學生陣列放到暫時的學生陣列
result = studentArray.sort(((s1, s2) -> s1.getName().compareTo(s2.getName())));
// 將原本的學生陣列設置成暫時的學生陣列(排好的)
studentArray.setArr(result.getArr());
break;
// 若輸入沒有此規則編號
default:
System.out.println("沒有此排序方法編號");
break;
}
}
/** 將學生物件重新打亂排序
* @param studentArray 要打亂順序的學生陣列
*/
public static void randomSequence(StudentArray studentArray) {
// 將學生陣列淺拷貝到 sequence
Student[] sequence = studentArray.getArr();
// 創建隨機物件
Random random = new Random();
// 使用迴圈將每個打亂順序
for (int i = 0; i < studentArray.getCount(); i++) {
// 隨機產生 0 ~ (studentArray.getCount() - 1) 的正整數
int p = random.nextInt(studentArray.getCount());
// 創建暫時的學生物件用來保留學生 ( sequence[i] )
Student tmp = sequence[i];
// 將學生 ( sequence[i] ) 換成隨機位置的學生( sequence[p] )
sequence[i] = sequence[p];
// 將隨機位置的學生( sequence[p] ) 換成學生 ( sequence[i] )
sequence[p] = tmp;
}
// 將重新排序的學生陣列賦予到學生陣列
studentArray.setArr(sequence);
}
}
```