CMoney菁英軟體工程師訓練營第四屆
===
## 2/25(day1)
### 額外
自動化玩具 ifttt、workflow
design pattern [非關語言: 設計模式](https://openhome.cc/Gossip/DesignPattern/)
### 命名規則
[命名規則參閱](https://www.javaworld.com.tw/jute/post/view?bid=20&id=27897&sty=1&tpg=1&age=0)
Project name 大寫起頭 駝峰式命名
package name 全小寫命名
Class name 大寫開頭 駝峰命名
variable, function name 小寫非數字開頭,駝峰式命名
宣告為final的變數(不可更動值)則全部大寫
### 變數
小數點預設為double
```java=
float f = 3.0f;
```
```java=
int num1, num2;
num1 = num2 = 0;
```
宣告連續變數,程式一律都是右邊開始執行
### 進制轉換
2->10
10->2
...
### 字元表示法
ASCII
java以Unicode存放char並且是2byte,所以可以存放中文字
### 強制轉型必要性
省略不必要的位數,過濾資料
```java=
float f = (int)3.66666;
System.out.println(f);
// 3.0
```
### 基本資料型態&參照資料型態
java的基本資料型態包含int(4)、float(4)、boolean(1)、char(2)、double(8)、short(2)、long(8)、byte(1)*(括號內為byte數)*
當宣告基本資料型態變數時,是宣告一個標籤,標籤的位址存放基本資料型態變數的值;而當宣告一個參照資料型態,同樣宣告一個標籤,此標籤存放的值為這個==物件實體的位址==。
## 2/26(day2)
### 格式化字串
```java=
float f = 1.3333f;
System.out.printf("%.2f", f);
// 1.33
```
### if/else判斷
綜合所得税&累進稅率計算(不同級距採if/else if方式)
#### & and &&
& 表示前後都要判斷
&& 若前面的判斷為false,則不需要判斷後面的判斷式,可以省判斷
| and || 也是同樣機制
```java=
// &&
int a = 80;
boolean c = true;
boolean d = false;
if(a >= 80 && (c = d)){
...
}
```
### switch case
### 算術指定運算子
需考量優先級
++ 與 小括號 同級別,故從左而右算
```java=
a += 1;
a++; // 先給後加
++a; // 先加後給
```
```java=
int a = 1;
int b = 0;
b = a++;
// a = 2
// b = 1
```
```java=
int a = 1;
int b = 0;
b = ++a;
// a = 2
// b = 2
```
```java=
int a = 1;
int b = 0;
b = a++ + ++a; // 1 + 3
// a = 3
// b = 4
```
```java=
int c = 0;
int b = 0;
while(c < 3){
b += ++c;
}
System.out.println(b + " " + c);
// 6 3
```
```java=
int c = 0;
int b = 0;
while(c < 3){
b += c++;
}
System.out.println(b + " " + c);
// 3 3
```
### 進制轉換
10 -> 2
2 -> 8 將二進制3數為一組
2 -> 16 將二進制4數為一組
## 2/27(day3)
### while / for
可於迴圈中加入變數當作計數器,用以計算迴圈重複的次數。
### do while
```java=
Scanner scanner = new Scanner(System.in);
int n;
do{
n = scanner.nextInt();
}while(n != -1);
```
#### 星狀圖
各式圖形、倒三角、直角三角、等腰三角、菱形...
1. 空心平行四邊形
```java=
int n = scanner.nextInt();
for(int i = 1; i <= n; i++){
// 做空格
for(int j = 0; j < n - i; j++){
System.out.print(" ");
}
for(int j = 1; j <= n; j++){
if(i > 1 && i < n && j > 1 && j < n){
System.out.print(" ");
}else{
System.out.print("*");
}
}
System.out.println();
}
```
2. 實心菱形(兩塊)
```java=
//上半塊
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n-i; j++){
System.out.print(" ");
}
for(int j = 1; j <= 2*i-1; j++){
System.out.print("*");
}
System.out.println();
}
//下半塊
for(int i = n+1; i <= 2*n-1; i++){
for(int j = 1; j <= i-n; j++){
System.out.print(" ");
}
for(int j = 1; j <= 4*n-1-2*i; j++){
System.out.print("*");
}
System.out.println();
}
```
3. 實心菱形(一塊)
:::info
==絕對值==想法實作
:::
```java=
int n = scanner.nextInt();
for(int i = 1; i <= 2*n-1; i++){
for(int j = 1; j <= (int)Math.abs(n-i) ; j++){
System.out.print(" ");
}
for(int j = 1; j <= (2*n-1)-(int)Math.abs(2*(i-n)); j++){
System.out.print("*");
}
System.out.println();
}
```
4. 空心菱形
```java=
int n = scanner.nextInt();
for(int i = 1; i <= 2*n-1; i++){
// 左方空白(倒直角三角、直角三角)
for(int j = 1; j <= (int)Math.abs(n-i) ; j++){
System.out.print(" ");
}
System.out.print("*"); // 左方星號
// 第2到第2*n-1層
// 中間空白部分
// 以正中為主分割兩邊
// 左方空白數從0到n-2
// (n-2)-Math.abs(i-n) 層數距離n越遠,空白數越少,故為減數
// 正中空白數固定1個
// 右方空白數與左方同樣,乘2即可
if(i > 1 && i < 2*n-1){
for(int j = 0; j < 2*((n-2)-Math.abs(i-n))+1; j++){
System.out.print(" ");
}
System.out.print("*"); //右方星號
}
System.out.println();
}
```
## 3/4(day4)
### 陣列
是一個參考資料型態,會於heap當中創造連續記憶體空間,用以存放型態相同的資料,所以存放的地址即為“第1個元素的位置(index = 0)”
所以array在搜尋資料的速度很快,直接加上“第幾筆*宣告的資料結構大小”,即為第幾筆資料的記憶體位址。
```java=
int nums[] = new int[5];
// 有一個叫做 nums 的標籤
// stack存放的值為new出的實體的記憶體空間位址
// 這個值也同樣是 陣列第一個元素的記憶體位址
```
:::info
**nums 與 nums[0]的差異**
nums -> addr's value (整個陣列)
nums[0] -> value(stored in addr) (值)
:::
==當我們創建了一個**參考資料型態**的陣列,每個陣列值存放的是這群實體各自的記憶體位址==
```java=
// example
NewClass[] nc = new NewClass[5];
// nc的stack 存放 new NewClass()建立的實體的記憶體位址
System.out.println(nc); // [Lcmoneyclass.NewClass;@1540e19d
System.out.println(nc[0]); // null
// 仍須各自new出新的記憶體空間來指派給各自的值
// 並非同時new出多個實體
```
## 3/5(day5)
### 函式function
類似功能寫成函式,更動的數值設計為變數。
#### 靜態方法static
不需類別物件實體即可使用的方法
#### 技巧:利用return將void函式強制回傳
可以適用於多層巢狀迴圈的打斷(將巢狀迴圈包裹於void函式中),因為可能在內部迴圈結束時即break出此巢狀迴圈,但break只能跳出最近的迴圈,無法跳出外部的迴圈。
#### 傳值呼叫

```java=
int a[] = new int[2];
a[0] = 1;
a[1] = 2;
func(a);
System.out.println(a[0]);
// 5
```
```java=
public static void func(int b[]){
// 新開了一個b[]的標籤,存放傳入的a陣列地址
// 所以更動此地址所指的記憶體空間
// 同樣會影響到原有a陣列
b[0] = 5;
}
```
## 3/6(day6)
### 排序
1. bubble sort
```java=
public static void bubbleSort(int[] arr){
// 找出第幾大的數字 第1次第1大 第2次第2大...
for(int i = 0; i < arr.length-1; i++){
// 檢查剩下的每一元素,如果較大則交換
// 跑完 即 將當次最大數往右排
for(int j = 0; j < arr.length-1-i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
}
```
2. insertion sort
3. selection sort
##### 問:利用XOR來實現變數互換?
[如何交換兩個變數,而不動用第三個變數?](http://clifflin123456.pixnet.net/blog/post/44902733-%E5%A6%82%E4%BD%95%E4%BA%A4%E6%8F%9B%E5%85%A9%E5%80%8B%E8%AE%8A%E6%95%B8%EF%BC%8C%E8%80%8C%E4%B8%8D%E5%8B%95%E7%94%A8%E7%AC%AC%E4%B8%89%E5%80%8B%E8%AE%8A%E6%95%B8%3F-%E5%88%A9)
主要想法來自於兩個變數的二進制,不需要額外的變數即可達到變數交換的效果。
> example :
> x = 5 = 101
> y = 6 = 110
> > 兩數使用XOR來做交換
> x = x XOR y = 011 = 3
> y = x XOR y = 101 = 5
> x = x XOR y = 110 = 6
> > > x = 6
> > > y = 5
### 隨機數
利用Math.random()函數可用來設定隨機數字。
```java=
Math.random() // return a float between 0 to 1
```
* 實例應用:選取一個範圍中的隨機數
想法:因為Math.random()會回傳0~1之間的隨機小數,0與1之間的間隔為1,要將此間隔擴大至所需的範圍+1,所以乘以範圍再加上最小值進行平移。
```java=
public static int randomNum(int min, int max){
return (int)(Math.random()*(max-min+1))+min;
}
```
* 實例應用:創建一個儲存值亂序的陣列
想法:首先設定一個內容值為其索引值的陣列,接著將針對其中第i個值,從剩下(num-i)個值中隨機抽取出一個做調換。
```java=
public static int[] getRandArr(int num){
int[] randArr = new int[num];
// set value
for(int i = 0; i < num; i++){
randArr[i] = i;
}
// 第 i 張牌與後方隨機(num-i)張牌互換
for(int i = 0; i < num; i++){
swap(randArr, i, getRandNum(i+1, num));
}
return randArr;
}
```
### 課堂練習
1. 成績排序(by座號)(by成績)
2. 排亂順序輸出
3. 撲克牌發牌(不重複值亂序陣列)
## 3/7(day7)
### 多維陣列
在java中,是以一個一維陣列的各個元素各自指向其他的一維陣列。表示第一個一維陣列存放各自指向的一維陣列的位址。
```java=
// 先開一個大小為3的一維陣列
// 存放大小為4的一維陣列的位址
// 大小為4的陣列存放實際的值
int[][] array = new int[3][4];
```
在記憶體操控方面會相較C語言的其中一種方式("直接開一個要的大小"&與"java相同機制")更為靈活,能夠配置空間較小的多個陣列實體。
#### 陣列記憶體控制
* 倍增一維陣列存放空間
```java=
public static void main(String[] args){
int[] nums = new int[5];
}
public static int[] doubleArr(int[] arr){
int[] tmpArr = new int[arr.length*2];
for(int i = 0; i < arr.length; i++){
tmpArr[i] = arr[i];
}
// arr = tmpArr;
// 這行表示將arr陣列指向新開的tmpArr陣列位址
// 但此時nums仍指向原有的nums陣列實體
return tmpArr;
}
```
:::info
Q:**為什麼需要將欲改變大小的陣列位址回傳?傳入陣列來做操作不是就是針對傳入地址的陣列來做改變了嗎?**
A:當傳入一個陣列,會在stack中新增一個標籤(arr)來指向原有的陣列位址,而我們需要一個新的2倍大小的陣列時,必須在heap中新開一個兩倍大小的陣列實體,並用新的標籤(tmpArr)去指向這個實體,再將原有的數值一一複製過去,最後回傳兩倍大小陣列實體的位址回去。
如果只將新開的標籤(tmpArr)所存的位址重新指派給原先指向陣列的標籤(arr),則原先的標籤(nums)所指向的位址仍非兩倍大小的陣列實體。(如圖一)
(圖一)
:::
* 倍增二維陣列存放空間(第二維其中一個)
假如想要只倍增nums[2][2]的第二維空間大小,則不需要將陣列位址回傳也可以。
原因在於,當我們傳入一個想要倍增第二維空間大小的二維陣列,我們不需要針對第一維存放的位址做任何的改變,只要創建出新的兩倍大小的一維陣列來將數值重新指派即可。
如圖二的步驟。
:::success
==step1==:原先的nums標籤指向一個大小為2的一維陣列實體,分別存放一個大小為2的一維陣列地址。
==step2==:將欲倍增的陣列傳入,會先宣告一個arr的二維陣列標籤指向nums所指向的陣列實體。
==step3==:再宣告一個一維陣列標籤tmpArr來指向兩倍大小的新陣列實體。
==step4==:分別將原有陣列的值指派給倍增的陣列。
==step5==:最後將倍增大小的陣列地址指派給欲擴增的的陣列。(原先指向的陣列實體,會交由gc機制來做回收。)
:::
(圖二)
```java=
public static void main(String[] args){
int[][] nums = new int[2][2];
}
public static void doubleArrr(int arr[][]){
int[] tmpArr = new int[arr[0].length*2];
for(int i = 0; i < arr[0].length; i++){
tmpArr[i] = arr[0][i];
}
arr[0] = tmpArr;
}
```
* 倍增二維陣列存放空間(全部)(假設每個大小都相同)(2x2->4x4->8x8...)
==想法==:直接開一個,再將值複製過去。
```java=
public static void main(String[] args){
int[][] nums = new int[2][2];
}
public static int[][] doubleArrrr(int[][] arr){
int[][] tmpArr = new int[arr.length*2][arr[0].length*2];
for(int i = 0; i < arr.length; i++){
for(int j = 0; j < arr[0].length; j++){
tmpArr[i][j] = arr[i][j];
}
}
return tmpArr;
}
```
* 倍增二維陣列存放空間(第一維)
==想法==:將第一維擴大,再將擴大的地方new出新的空間asign回去。不然第一維擴大的部分沒有新的空間指向他。
```java=
public static int[][] doubleArr(int[][] arr){
int[][] tmpArr = new int[arr.length*2][];
for(int i = 0; i < arr.length; i++){
tmpArr[i] = arr[i];
}
for(int i = arr.length; i < arr.length*2; i++){
// 倍增的部分再new出新的實體給他
tmpArr[i] = new int[arr[0].length];
}
return tmpArr;
}
```
## 3/8(day8)
* 課中練習檢討:擴增陣列存放學生資料並排序
* 額外練習講解:1A2B猜數字遊戲(手動猜&電腦猜)
### 1A2B猜數字(手動猜)
==想法==:問題拆解成許多小問題,像是需要check每一次有幾A幾B、將數值各個位數以陣列存放、判斷是否有重複數字的四位數字...
### 1A2B猜數字(電腦猜)
==想法==:每次先猜1234,或是接著猜5678,當有第一次的AB數量時,從所有可能的答案中找出同樣AB數量的答案,再從這些篩選過的答案中去隨機猜,每次都去核對AB數量,再次剔除掉AB數量不同的答案,使隨機猜的範圍逐漸變小,重複直到猜中。
### 練習:讀取字串並計算字串數量
#### 利用array實作dictionary
dictionary可以關鍵字來查詢特定位置的資料,在其他語言中,可以透過給予key值來查找這個key值身上的資料,在此以array的方式來實作。
==實作想法==:
```java=
// 陣列初始大小
String[] strings = new String[2];
// 陣列實際存有值的數量
int count = 0;
// 關鍵字陣列(不重複)
String[] dictionary = new String[2];
int[] nums = new int[2]; // 紀錄每個關鍵字的數量
int j;
int dictionaryCount = 0; // 記錄dictionary中值的數量
for(int i = 0; i < count; i++){
for(j = 0; j < dictionaryCount; j++){
if(dictionary[j].equals(strings[i])){
nums[j]++;
break;
}
}
// 表示有新的字典關鍵字需要加入
if(j == dictionaryCount){
dictionary[j] = strings[i];
nums[j]++; // 加入的關鍵字數量設為1
dictionaryCount++;
}
// 倍增陣列存放空間
if(dictionaryCount == dictionary.length){
dictionary = doubleStringArr(dictionary);
nums = doubleIntArr(nums);
}
}
```
## 3/11(day9)
* test2
### 字串
* ASCII code
* 字元 & int 互換
* String Pool
在heap中有一個特別的空間(String Pool),用來存放所有傳入字串的地址。
ex:
String Pool中存有"123"這個字串
```java=
String a = "123";
String b = "1" + "23";
System.out.println(a == b); // true
```
```java=
String a = "123";
String b = new String("123");
System.out.println(a == b); // false
```
所以當要比較兩個字串值是否相等,必須使用String.equal()方法。
### 字串物件的方法
* split()
給予切割字元,切出一個string array
* substring(start, end)
切出起始位置到結束位置-1的值,總計(end - start)字元。
* 其他 可參閱 7.3 ppt or 上網查
### 遞迴
#### 費氏數列(遞迴)(非遞迴)寫法
==*遞迴版本*==
```java=
public static int fibonacciByRecursion(int num){
if(num == 1) return 1;
if(num == 0) return 0;
return fibonacciByRecursion(num-1) + fibonacciByRecursion(num-2);
}
```
==*非遞迴版本*==
```java=
public static int fibonacciByForLoop(int num){
// 陣列大小為費氏數+1的原因在於 f(0)=0
// 當想要求f(10)時,實際上需要10+1個空間大小
int[] nums = new int[num+1];
// 藉由陣列來存放每個費氏數的值
for(int i = 0; i < num+1; i++){
if(i == 1) nums[i] = 1;
if(i == 0) nums[i] = 0;
if(i > 1){
nums[i] = nums[i-1] + nums[i-2];
}
}
return nums[num];
}
```
#### 河內塔
有n個盤子和三座塔(A、B、C),需要將盤子從A塔移到C塔,其中每個盤子上都有各自的編號,移動的過程必須符合以下規定:一次動一個盤子,編號大的盤子不能疊在編號小的盤子上。
==遞迴想法==:
主要分成三個步驟:
步驟一:首先將(n-1)個盤子從A塔移動至B塔。
步驟二:再將剩下的那個最大盤子從A塔移動至C塔。
步驟三:最後將B塔的(n-1)個盤子從B塔移動至C塔。
base case:當只有1個盤子時,印出移動過程。
```java=
public static void hanoi(int plate, char start, char terminal, char tmp){
// base case
if(plate == 1){
System.out.println("from " + start + " to " + terminal);
return;
}
hanoi(plate-1, start, tmp, terminal); // step 1
hanoi(1, start, terminal, tmp); // step 2
hanoi(plate-1, tmp, terminal, start); // step 3
}
```
## 3/12(day10)
### 函式多載(overloading)
相同函式名稱可以同時存在,但給予的參數必須不同,且回傳值的類型必須相同。
舉例:swap()方法,用來交換一維或是二維陣列,傳入不同維但可以同樣實現交換的方法。
### 物件導向
任何物件都在類別之下,身上具有屬性及方法,與一般結構式語言(C/C++)不同,缺點可能在於效能會差一點,但好處在於易於程式設計。
#### static靜態方法
與類別相同層級,不需要有類別的實體即可使用的屬性或方法。
#### 封裝(encapsulation)
封裝性適用於將設計好的類別給別人使用時,給予不同的權限設計,用來避免設計好的類別內容遭人更改。
* public
* private
* protected
* default
但可藉由setter/getter來間接存取修改屬性值。
#### 建構子(constructor)
當物件實體產生時,會自動執行的方法,用來將傳入參數指派給物件身上的屬性。當不寫建構子時,會自動產生一個空的建構子。若當創建了建構子時,空的建構子會被刪掉,若有空建構子的需求,必須再自行創建。
建構子也有overloading的概念,所以可以創建多個不同參數的建構子。
*若要傳入陣列當作參數,不要將空間在類別中new出來,在建構子中設計。*
#### this關鍵字
this關鍵字在執行時是指現在這個類別操作的物件實體,而在類別中寫到這個關鍵字則是表示這個類別本身,所以我們可以將傳入參數帶入此物件身上的屬性。
```java=
/* MyClass.java */
public class Myclass(){
int width;
int height;
// 建構子
public MyClass(int w, int h){
this.width = w;
this.height = h;
}
}
```
```java=
public class Tester(){
public static void main(String[] args){
MyClass mc = new MyClass(5, 3);
System.out.println(mc.width); // 5
System.out.println(mc.height); // 3
}
}
```
#### toString()
當使用System.out.print()方法時,會將傳入的物件,呼叫他身上toString()方法,將非String的值,回傳成String,所以可以修改身上的toString()方法,來將物件想要印出的內容印出,否則會印出此物件的地址。
```java=
/* main */
public class Main{
public static void main(String[] args){
NewClass nc = new NewClass();
System.out.println(nc); // nc地址
}
}
```
```java=
/* NewClass */
public class NewClass{
/* attributes...
* constructor...
* */
public String toString(){
String strings;
strings = attribute1 + " " + attribute2 + " ";
return strings;
}
}
```
將我們在類別中設定自己的toString()方法,實際上是複寫(overide)了object最上層類別的方法,就可以印出自己想要輸出的東西。
#### 物件陣列
```java=
Student[] students = new Student[10];
// 創建出一個10格的陣列空間想要用來存放學生物件的地址
// (內容都為null,還沒有學生物件的實體)
students[0] = new Student("kj", "大象", 100, 98, 99);
```
如下圖所示:(實際記憶體配置狀況)

所以當我們要存取或是寫入類別物件陣列的元素時,必須先將他new出來。
## 3/13(day11)
* 學生類別實作講解
* 加入學生陣列類別改寫
將分工細分
類別設計中,可以在類別中宣告自己的類別,也能夠在方法中傳入自己的類別,只是在設計上要小心。
而在封裝等級上,若如入自己類別的參數,能夠直接取得private的參數,而不需要透過getXXX()的方法,因為類別相同而層級相同。
```java=
public class Rectangle(){
int width;
int height;
public Rectangle(int w, int h){
this.width = w;
this.height = h;
}
// 比較兩長方形大小
public int compare(Rectangle rectangle){
if(this.getArea() > rectangle.getArea()){
return 1;
}else return 0;
}
}
```
* 出牌遊戲實作
* Uno
## 3/14(day12)
* 出牌遊戲實作
* Uno
### String.next()與String.nextLine()的差別
## 3/15(day13)
### 課堂實作講解
#### static
==好用,但不可濫用。==
在類別實體建成之前就開了一個空間給static屬性或方法,當我有多個類別實體,全部都共用同一個static空間,所以若是其中一個物件更改了static屬性或方法,同樣類別的所有物件的static屬性或方法都會被修改。
通常使用於不會更動的常數屬性或方法。
### final
不可更動的屬性,必須在建立時即初始化。
## 3/18(day14)
* 測驗3
* 講解測驗3
## 3/19(day15)
### 繼承
取得父類別屬性在類別中採用super關鍵字來表示父類別。
父類別建構子會比子類別建構子優先執行,而當父類別具有不為空的建構子時,必須在子類別的建構子中呼叫父類別建構子,將父類別建構子的事情先做完,才會做子類別的建構子。
所以==父類別建構子必須寫在子類別建構子的第一行,確保父類別要做的事情都先做完。==
### 繼承的屬性
當繼承自父類別的屬性要取用時,一般都以super.getter()方法來做取用,而當子類別中也有同名屬性時,父類別的屬性會隱藏,但仍佔有記憶體空間,在調用時以this和super來做區別。
### Override
當我們複寫方法時,回傳值的型態受到規範,也就是說可以回傳原先類別,或是繼承自原先類別的子類別型態,因為子類別繼承自父類別,應該可以達成所有父類別能夠完成的事情。
而複寫(Override)與多載(Overloading)的差別在於複寫是將父類別的方法來做改寫,一般會加上"@Override"來告知系統;而多載是相同名稱的方法具有不同的傳入參數。
***以String.toString()來做範例***
```java=
@Override
public String toString(){
return "這是Override";
}
```
```java=
public String toString(int num){
return "這是Overloading" + num;
}
```
## 3/20(day16)
### Object類別
所有物件都會繼承的父類別,在java中也是唯一一個沒有父類別的類別。當一個類別沒有繼承任何類別時,系統會自動繼承Object類別。
### 多型
父類別物件可以以子類別的物件實體來儲存,因為子類別的物件實體中必定包含父類別物件的實體。
#### downcasting
```java=
Shape[] shapes = new Shape[2];
shapes[0] = new Rectangle(3, 5);
```
#### 多型應用範例
```java=
// shape父類別
Shape[] shapes = new Shape[5];
shapes[0] = new Rectangle(3, 5);
shapes[1] = new Circle(5);
shapes[2] = new Rectangle(1, 7);
shapes[3] = new Circle(3);
shapes[4] = new Rectangle(7, 9);
```
## 3/21(day17)
* 生態系實作
## 3/22(day18)
### 泛型
在Java中已經先幫我們實作出一些資料結構,可以直接使用身上的方法,而不需要自己去寫doubleArr()、getCount()之類的方法。
以ArrayList來做說明,<>在這個diamond符號中的類別,表示這個ArrayList中能夠存放的類別,
```java=
ArrayList<Integer> nums = new ArrayList<>();
nums.add(3);
nums.add(2);
nums.add(1);
```
### 資料結構(array、linkedList)
* array
連續記憶體空間,
* linkedList
不需連續的記憶體空間
```java=
// 實作
// 包含 add()、remove()、get()、insert()、size()方法
```
## 3/25(day19)
* test4
筆試:記憶體管理、進制轉換、手寫程式碼(卡牌)
上機:形狀類別 & 高鐵購票系統
## 3/26(day20)
* test4檢討
### 檔案管理
* BufferedWriter
* BufferedReader
> *增加效能的作法為減少與外面檔案io的次數*
java中採用==buffer緩衝區==的做法增加效能,先將一定大小的資料流存進緩衝區,等到需要用到時才從緩衝區將資料拉進來處理,可以減少與外頭檔案io的次數。*緩衝區在記憶體中、外頭檔案在硬碟中*
::: warning
記得每次開啟檔案讀取或寫入完成後都要將檔案關閉。
:::
***在實際使用時,通常都是將檔名傳入寫/讀檔案的function,在function中新建BufferedWriter、BufferedReader來做處理。
而在檔案存讀取的時候,盡量先將資料先存入預想的資料結構中,若是之後還有處理檔案的需求則能夠直接使用這些資料,待所有處理都結束時才將檔案寫入。***
## 3/27(day21)
### 檔案管理系統練習
* 學生資訊系統
* 捷運系統
## 3/28(day22)
* 捷運系統
## 3/29(day23)
* 捷運系統
## 4/1(day24)
* test_5
### 介面(Interface)
其中只能有常數以及抽象方法,方法教給時做這個界面的類別來實作。較常使用於責任歸屬的區分上,介面能夠實現多種抽象方法,讓實作同一個介面的類別能夠達成不同的方法。
interface :
```java=
```
* slime史萊姆戰鬥
## 4/2(day25)
### 內部類別
若是此類別只服務特定的類別,例如LinkedList中的Node,可以將此類別寫在LinkedList類別其中。需要上層類別的實體才能建構出此內部類別的實體。
### 靜態內部類別
若有需要直接取得內部類別,可以將內部類別設置為靜態方法,可以讓其不需要外部類別實體即可創建。
### 匿名內部類別
當我們需要一個類別來實現實作介面,但此類別只被使用到一次,我們可以直接在需要使用它的地方,創建出一個匿名類別實體直接實現介面的實作,但不需要直接開一個新的類別給他。
* 進階史萊姆戰鬥
## 4/3(day26)
* 進階史萊姆戰鬥
* LinkedList講解 & 技巧
***ArrayList & LinkedList差別以及優缺***
* ArrayList
查找快
* Linkedist
## 4/8(day27)
* test6
* 加總計算(遞迴、讀寫檔練習)
## 4/9(day28)
### java動畫與繪圖
### Adapter
是一個實現了多個介面的類別,可以繼承這個類別來選擇自己想要改寫的介面方法,才不需要通通實現。(如果自己實現這些介面會讓整體程式碼變得太過雜亂)
### 共同類別存放共通屬性
圖片的座標、繪製出來的方法
:::info
**若將圖片檔存在共通的類別呢?**
*共通的類別不會存圖檔,可以交給繼承此類別的子類別來存
若有許多相同怪物使用同一張圖 -> 可以採用static來存圖片
但若是有許多不同的怪物,則需要有不同的類別來各自存放,但行動都一樣,卻需要開這麼多類別...
比較好的做法是
將圖片共同存入一個資源庫
只要有使用到圖片的時候,就將存放圖片的位置回傳*
:::
## 4/10(day29)
* java動畫與繪圖
* 隨機生成 & 碰撞 & 射擊
* KeyEvent類別用法
## 4/11(day30)
### 解決ImageIO重複讀取檔案效能問題
* 可以採用static(但換圖會出問題)
若是同一個角色類別會運用到不同張圖,則會將圖一起換掉。
* 資源管理器(類別)
這個類別中會存放共同的資源,
## 4/12(day31)
* RPG製作練習
## 4/15(day32)
* abstract class 抽象類別
## 4/16(day33)
### 版本控制
* BitBucket & SourceTree
## 4/17(day34)
* 期中專題
## 4/18(day35)
### 例外處理
* Error
嚴重的系統錯誤,通常不處理,直接拋出錯誤訊息。
* Exception
通常不為系統所發生的錯誤,多數來自變數或執行上才發生的例外。
#### try...catch...finally
用來處理有可能發生例外的狀況。
```java=
try{
// (預計要做的事情)
// 有可能會發生例外的狀況
// 當狀況發生時,直接拋出例外
// 拋出例外程式碼以下的程式碼不會被執行到
} catch(MyException e){
// 當接到此例外時,做處理
} finally{
// 無論如何都會執行的部分
// 即便在try或catch之中已經有return
// 同樣會執行
}
```
* Example
```java=
try{
System.out.println("try");
throw SomeException;
System.out.println("not reach");
} catch(SomeException e){
System.out.println("deal with exception");
return 0;
} finally{
System.out.println("finally");
return 1;
}
// try
// deal with exception
// finally
// return回去的值 "1"
```
:::info
**多型 可能會遇到狀況**
* 當在父類別的方法中嘗試拋出例外,在子類別的方法中,若是改寫了父類別的此方法,若是同樣可能會拋出例外,沒辦法去拋出父類別設定的例外層級以上的例外,只能拋出父類別拋出例外層級之下的例外(繼承自父類別例外的子例外)。
* 原因在於若有多個子類別去改寫這些方法,可能會拋出不同的例外,若是此例外不屬於父類別例外的子例外,則無法接受設定的處理,==不在父類別例外的處理範圍中了==。
:::
* Example
```java=
// 父類別
public class Shape {
// 自己設計的例外
public class SomeException extends Exception{
public SomeException(String msg){
super(msg);
}
// 父類別中可能會拋出例外的方法
public int getArea() throws SomeException{
System.out.println("try");
throw new SomeException("there is something wrong");
}
}
```
```java=
// 子類別
public class Rectangle extends Shape{
// 改寫父類別中可能會拋出例外的方法
// 可以不拋出,若要拋出
// 必須拋出父類別拋出的例外層級以下或相同的例外
@Override
public int getArea() throws SomeException{
throw new SomeException("例外的子類別");
}
// 拋出父類別可能拋出層級的例外會報錯
// @Override
// public int getArea() throws Exception{
// throw new Exception("");
// }
}
```
## 4/19(day36)
* 遊戲專題
## 4/22(day37)
### 測驗8講解
StringArrayList與StringLinkedList以介面(Iterator)及抽象類別(List)實作,並加入concat()方法設計。
### 泛型
只能夠將型別宣告為參考資料型態,不能宣告為基本基料型態。
#### 以泛型實作LinkedList
* 自己練習
### Stack
:::info
一般程式執行時,即是創建了許多系統的stack來記錄執行的順序以及回傳的地址。
而遞迴之所以慢,就是創建了許多stack,等到執行到終止條件時,逐漸將回傳值一個個pop()回來。
:::
stack中主要包含push()、pop()兩種方法
push():將資料加入stack中。
pop():將頂端資料取出回傳,並從stack中移除。
==額外方法==
peek():傳回頂端資料,但不將資料從stack中移除。
* 可實際應用於 "上一頁下一頁"的機制
* 走迷宮練習
```java=
// 迷宮路徑搜尋
//
```
## 4/23(day38)
* 遊戲專題
## 4/24(day39)
* 期中專題階段發表
(待補)
1. 需要修改的部分...
共通問題:
1. 扣緊故事
2. 遊戲說明
3. 分工詳細說明
4. 簡報前後呼應,要有完整性
## 4/25(day40)
* 遊戲專題
## 4/26(day41)
* 遊戲專題
## 4/29(day42)
* test9
### Queue
通常會應用於"執行緒"相關。
:::info
例如:購票系統 or 網路request
當許多的request進入到系統中,不可以出現超賣票卷的情況,因此只要加進queue之中再慢慢處理即可,後續超過的部分就不處理。
:::
#### queue處理方式
以ArrayList來實現會有front和rear重疊的情況,無法新增值,但queue卻為空的情形。
* 環狀queue來處理
## 4/30(day43)
### 雜湊Hashing
查找對應內容速度最快:O(1)
經由hash公式換算出對應的記憶體位置,直接去記憶體位置拿資料。
#### 理想Hashing
#### Hashing 碰撞 & 溢出
:::info
討論
* 如何選擇 hash function(降低碰撞)
* 如何處理 Overflow)
* 如何設定 hash table 的大小
:::
#### 數位簽章
* Token
當使用者傳送帳號密碼給伺服器端,伺服器端會將id、時間戳記以及傳送request後拿到的hash值,打包成一個Token,回傳給使用者,讓使用者接下來不需要再打密碼就能夠使用服務,只要回傳token,伺服器端就能確認使用者是本人。
## 5/2(day44)
* 遊戲專題 demo day
## 5/3(day45)
* 遊戲專題
## 5/6(day46)
* Test10 - Queue & Stack 實作應用
* Android Studio 安裝
## 5/7(day47)
### Android Studio
package name是在googleplay商店上架用來識別有無重複的依據。也同樣是專案在電腦中的檔案架構。
### activity簡介與生命週期

### XML檔案與LinearLayout
是一種文本格式,跟json相同。Andriod Studio會依據此XML文件來生成對應的程式碼。
在Android中所有的元件都是View的子類別(比較像是Component的概念),都會在一個Container中。
### Margin & Padding
Margin與元件的外間距
Padding與元件的內間距
### Weight
依據所有元件的比重來分配自己在剩餘空間的大小
* weightSum
### Id
透過id來將java檔與xml文件做連結。
## 5/8(day48)
### Andriod Studio基礎元件
### Memory Leak 記憶體流失
## 5/9(day49)
### Json
#### JsonObject
#### JsonArray
### SharedPreference
## 5/10(day50)
* 遊戲專題
## 5/13(day51)
* test11 - Android Studio 拉畫面
## 5/14(day52)
* 遊戲專題
## 5/15(day53)
* 遊戲專題
* 期中發表彩排
## 5/16(day54)
* 最後衝刺
## 5/17(day55)
* 期中遊戲專題發表
## 5/20(day56)
* test12
### 二元搜尋法(binary search)
適用於已經排序好的陣列
:::info
要怎麼從雜亂數列中找到數?
視情況而定or直接找最快
:::
### 樹狀結構
### 二元樹
### AVL Tree
## 5/21(day57)
* 模擬面試
## 5/22(day58)
### 排序法 Sort
內部、外部排序
#### 各種搜尋法
* insertion sort
* selection sort
* quick sort
* merge sort
* * natual merge sort
切分出已經排好的片段,再將片段合併。
* heap sort
## 5/23(day59)
* natural merge sort實作
## 5/24(day60)
* natural merge sort實作
## 5/27(day61)
* test13
* 模擬面試
* 話題不要發散,回答問題只給答案就好,對方有興趣再說明
* 履歷寫到的點都需要跟應徵的工作有連結
### Shared Preference
用來儲存少量資料,紀錄應用程式的一些相關資訊。
```java=
private SharedPreferences sp;
sp = this.getSharedPreferences("DATA", MODE_PRIVATE);
// builder pattern 設計模式 回傳editor自己
// 寫入資料
sp.edit()
.putString("DATA_NAME", "test")
.putInt("DATA_AGE", 15)
.commit();
// commit(直接同步寫入) or apply(找時機寫入) 才會將資料寫入
// 取資料(第2個參數是自己給的預設值)
// 確保程式不會出錯,一定會有取到值
int i = sp.getInt("DATA_AGE", 0);
```
### 多執行緒(Thread)
電腦來回切換正在處理的程序(process),做一點點後切換。
通常process死亡後,其下的thread都會跟著死亡。
:::info
*為何網路連線都需要採用多執行緒?*
有網路不好的情況,若是只有單執行緒會造成程式直接卡死,會等待網路連線後才繼續執行程式。(UI會卡住)
需要採用多執行序分別負責網路連線以及UI控制的部分。
:::
## 5/28(day62)
### BuilderPattern(建造者模式)
用來處理建構子無法滿足所有使用情況時。
* 創建相同實體的builder
* 創建不同實體的builder
### Toast & AlertDialog
Toast會彈出視窗,顯示文字訊息一段時間。
AlertDialog繼承自Dialog類別,用來彈出可選擇使用選項按鈕的視窗等,
### 誰是臥底?畫面實作
* seekBar
* switch
* AlertDialog.builder
* LayoutInflator
## 5/29(day63)
### 頁面傳遞資訊
* Intent 傳遞值
* Bundle 打包成一包丟過去
* 序列化(sequentialable & parcelable)
### 改寫返回鍵
### 實現雙擊螢幕做特定事件
利用延遲與boolean來實現。
拉出類別以及介面來實現:
```java=
@Override
public void onBackPressed(){
ClickedUtil.clicked(isClicked, new ClickedEventListener() {
@Override
public void singleClicked() {
isClicked = true;
Toast.makeText(MainActivity.this, "single clicked", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isClicked = false;
}
}, 2000);
}
@Override
public void doubleClicked() {
Toast.makeText(MainActivity.this, "double clicked", Toast.LENGTH_SHORT).show();
MainActivity.super.onBackPressed();
}
});
}
```
```java=
public interface ClickedEventListener {
void singleClicked();
void doubleClicked();
}
```
## 5/30(day64)
* 誰是臥底?實作
## 5/31(day65)
* 誰是臥底?實作
## 6/3(day66)
* test14
### RecyclerView
### Adapter Pattern
### Factory Pattern
## 6/4(day67)
### API
### GCP 環境建置
[GCP環境建置](https://hackmd.io/aBLvcH0HSHuD9HHUIXuzhg?both)
### Restful API
* GET
運用網址來取得資料(一般不用於傳遞具隱秘性的資料)
:::info
https://www.google.com/search?safe=off&client=firefox-b-d&q=jiejie&spell=1&sa=X&ved=0ahUKEwjv4ra6oc_iAhUtGKYKHX0rDOQQBQgrKAA&biw=1244&bih=681
* 裡面可以看到有些safe、client...的變數名稱,表示是採用get的方式來做資料傳遞
:::
* POST
* PUT
* DELETE
### CRUD
create、read、upload、delete
## 6/5(day68)
* 自主練習
## 6/6(day69)
* 自主練習
## 6/10(day70)
* Test_15(RecyclerView & JSON應用)
* 考試講解
## 6/11(day71)
### Android 連結api
* 連結"誰是臥底遊戲"?
採用"okhttp"此套件
[okhttp](https://github.com/square/okhttp)
### 網路連線功能封裝
## 6/12(day72)
### 拆分專案架構(以node.js)
### GET & POST
#### Get的方法
* params
* query
#### Post的方法
### CallBack function
[CallBack函式說明](http://fiend1120.pixnet.net/blog/post/196941375-callback-function)
## 6/13(day73)
### MongoDB建置
## 6/14(day74)
* 連接資料庫Api
## 6/17(day75)
* 會員註冊系統api撰寫
## 6/18(day76)
* 會員註冊系統api撰寫
## 6/19(day77)
* 會員註冊系統api撰寫
* 誰是臥底檢查
## 6/20(day78)
* Vue環境建置
## 6/21(day79)
* 期末專題提案
## 6/24(day80)
* 會員註冊&登入系統作業檢查
* API test16
## 6/25(day81)
* 期末專題討論
## 6/26(day82)
* 期末專題討論
## 6/27(day83)
* 期末專題討論
## 6/28(day84)
* Trello
* 專案開發技巧 看板方法
## 7/1(day85)
* 期末專題
## 7/2(day86)
* 加解密
* MD5
* RSA
* SHA
* JWT (JSON Web Token)
## 7/3(day87)
### Heap Sort
* heap sort 一般使用場景
外部排序
## 7/4(day88)
* 期末專題
## 7/5(day89)
* 期末專題
## 7/8(day90)
* 期末專題
## 7/9(day91)
### 設計模式-觀察者模式
### 設計模式-狀態模式
### And Or 邏輯閘實現
## 7/10(day92)
* 期末專題
## 7/11(day93)
* 期末專題
## 7/12(day94)
* 期末專題
## 7/15(day95)
* 期末專題
## 7/16(day96)
* 期末專題
## 7/17(day97)
* 期末專題
## 7/18(day98)
* 期末專題
## 7/19(day99)
* 期末專題
## 7/22 ~ 7/26(day100 ~ day104)
* 期末專題
## 7/29 ~ 8/2(day105 ~ day109)
* 期末專題
## 8/5 ~ 8/8(day110 ~ day113)
* 期末專題&期末發表彩排
## 8/9(day114)
* 颱風假
## 8/13(day115)
* 期末發表&結業式
## 8/14(day116)
* 公司企業參訪(全曜、上詠、錢管家、金尉、超級物種、MDBS)
## 8/15(day117)
* CMoney筆試
###### tags: `java`