# Java 8 筆記
###### 作者: TYT
###### tags: `Java`
## 物件變數在儲存空間的配置
```mermaid
graph TB
subgraph 儲存空間;
Global; Stack; Heap;
end
```
- Global (全域資料)
- 使用static宣告物件變數(稱「靜態變數」或「類變數」)的儲存空間
- 不同物件實體中,相同的靜態物件變數因指向相同的儲存位置,其值會互相干擾
:::spoiler 範例
```java
public class Demo {
static int a = 1;
int b = 2;
public static void main(String[] args) {
Demo d1 = new Demo();
d1.a = 10;
d1.b = 20;
System.out.println("d1.a: " + d1.a);
System.out.println("d1.b: " + d1.b;
System.out.println("----------");
Demo d2 = new Demo();
System.out.println("d2.a: " + d2.a);
System.out.println("d2.b: " + d2.b);
}
}
// 輸出:
// d1.a: 10
// d1.b: 20
// ---------
// d2.a: 10
// d2.b: 2
```
:::
- Stack (堆疊)
- 宣告物件變數屬於基本型態時,例如char, int等,皆儲存於Stack儲存空間
- 不同物件變數,即使值相同,亦配置於不同的位置
- 占用記憶體空間小,存取速度快
- Heap (堆積)
- 宣告變數屬於參考資料型態(非基本型態)時,例如String, List等,物件變數參考值(資料來源位址)儲存於Stack,資料實體(資料本身)儲存於Heap
- 不同的物件變數,其值相同時,會指向相同的Heap位置,故其值會互相干擾
## 新功能in Java 8
- ::語法
- 使方法(method)與匿名函數(lambda)像第一類物件的使用
:::spoiler 範例: 列出隱藏檔案
```java
// 一般使用
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
public boolean accept (File file){ // 過濾隱藏檔案
return file.isHidden();
}
})
// 像第一類物件般的使用
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
```
:::
- Predicate。抽象方法介面(functional interface)
- test方法,實際參數符合Predicate,return true, 否則false
:::spoiler 範例
```java
public static void main(String[] args){
Predicate<Integer> predicate = new Predicate<Integer>() {
public boolean test(Integer integer){
if (integer > 5) return true;
else return false;
System.out.println(predicate.test(3)); // false
System.out.println(predicate.test(6)); // true
}
```
:::
- ->語法,匿名函式(lambda)
- 適合一次性使用且簡單的方法
:::spoiler 範例
```java
List<Integer> list = Arrays.asList(3, 1, 4, 5, 2);
// 一般方法
list.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
// 匿名函式
list.sort((o1, o2) -> o1.compareTo(o2));
```
:::
- stream()
- 簡化需要多個迭代(迴圈)的運算,以及可多核心執行,加速效率
:::spoiler 範例
```java
List<String> list = Arrays.asList("a1", "a2", "b1", "c2", "c1");
// 一般方法
List<String> list2 = new ArrayList<String>();
for (String s1 : list) {
if (s1.startsWith("a")) {
list2.add(s1);
}
}
list2.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
for (String s2 : list2) {
System.out.println(s2);
}
// stream()
list.stream().filter(s1 -> s1.startsWith("a")).sorted().forEach(s2 -> System.out.println(s2));
//輸出:
// a1
// a2
```
:::
- parallelStream()
- 與stream()相似,但可進行平行運算,將Stream分成多個Stream並同時執行
:::spoiler 範例
```java
List<Integer> list = Arrays.asList(1, 3, 2, 4, 5);
// stream()
List<Integer> greaterThan3List = list.stream().filter(i -> i > 3).collect(Collectors.toList());
// parallelStream()
List<Integer> greaterThan3List = list.parallelStream().filter(i -> i > 3).collect(Collectors.toList());
```
:::
- <a id='行為參數化'>行為參數化(bahavior parameterization)</a>
- 方法做為參數傳入另一個方法,使主要方法可藉由行為參數實現不同的功能,即[策略模式](#策略模式)
- 缺點: 可能會導致過多class的產生
:::spoiler 範例
```java
public class Demo {
public static void main(String[] args) {
List<Apple> redAndHeavyApples = filter(inventory, new RedAndHeavyPredicate()); // 紅蘋果且重量大於150的清單
List<Apple> greenAndLightApples = filter(inventory, new GreenAndLightPredicate()); // 綠蘋果且重量小於150的清單
}
public List<Apple> filter(List<Apple> inventory, ApplePredicate p){ // ApplePredicate p -> 行為參數化
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory){
if (p.test(apple){
result.add(apple);
}
}
}
}
// 紅蘋果且重量大於150
public static class RedAndHeavyPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "red".equals(apple.getColor()) && apple.getWeight() > 150;
}
}
// 綠蘋果且重量小於150的清單
public static class GreenAndLightPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "green".equals(apple.getColor()) && apple.getWeight() < 150;
}
}
public interface ApplePredicate{
boolean test(Apple apple);
}
```
:::
- 匿名class
- 與匿名函式類似,適合一次性使用的class,但容易造成程式碼冗長且不好閱讀
- 與[行為參數化](#行為參數化)的範例對照,節省創建RedAndHeavyPredicate及GreenAndLightPredicate class
:::spoiler 範例
```java
List<Apple> redApples = filterApples(invetory, new ApplePredicate(){
public boolean test(Apple a){
return "red".equals(a.getColor());
}
})
```
:::
## 設計模式
- <a id='策略模式'>策略模式</a>
- 依據不同的場景,藉由替換介面中的實體方法,達到不同的行為實現,範例如[行為參數化](#行為參數化)
## 名詞解釋
- First-class object
- 第一類物件,又稱First-class citizen, First-class values, First-class entity
- 為一實體(entity),支持其他實體的一般性操作,可做為參數傳遞給方法、方法的return值、及儲存於Heap的儲存空間
- Second-class value
- 第二類物件,Second-class citizen, Second-class values, Second-class entity
- 為一實體,可做為參數傳遞,但不能做為方法的return值及被分配給變數
- varible
- 變數。
- ``` int var = 1;```中的```var```即為變數
- parameter
- 形式參數,又稱formal parameter。定義方法時,給定需傳入的變數
- ``` public void ping(int param) { //TODO } ``` 中的```param```即為形式參數
- argument
- 實際參數,又稱actual parameter。使用方法時,所傳入的變數
- ```ping(pong);```中的```pong```即為實際參數
## 主要參考資料
1. 蔡文龍、何嘉益、張志成、張力元。2019。Java SE 12基礎必修課。碁峰資訊股份有限公司。臺北。
2. Java 8 in Action: Lambdas, streams, and functional-style programming. 2014. R.-G. Urma, M. Fusco, and A. Mycroft. Manning Publications. NewYork.
3. Oracle and/or its affiliates. 1993, 2022. https://docs.oracle.com/javase/8/docs/api/overview-summary.html. Oracle and/or its affiliates.
## 版本
| 時間 | 項目 |
| --- | --- |
| 220327 | 新增物件變數在儲存空間的配置 |
| 220328 | 新增名詞解釋-First-class values |
| 220329 | 新增名詞解釋-Second-class value <br> 新增功能in Java 8-::語法、Predicate.test方法 |
| 220330 | 新增名詞解釋,variable, parameter, argument |
| 220331 | 新增功能in Java 8-\->語法 |
| 220401 | 新增功能in Java 8-stream() |
| 220403 | 新增功能in Java 8-parallelStream() |
| 220409 | 新增功能in Java 8-行為參數化、設計模式-策略模式 |
| 220414 | 新增功能in Java 8-匿名class |