---
# System prepended metadata

title: Java_Cmoney_Week2_介面練習
tags: [Cmoney_Java題目]

---

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

![](https://i.imgur.com/8HUula8.png)



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


```
