---
# System prepended metadata

title: Java 8 OCPJP Notes
tags: [java_se]

---

---
tags: java_se
---
# Java 8 OCPJP Notes

## Ch7 Exception

### 在 catch block reassign exception parameter

*Uni-Catch* clause
A catch clause whose exception parameter is denoted as a single class type is called a uni-catch clause.

在 catch blcok reassign exception parameter variable 後, 相當於又產生了一個新的 Exception. 必須 handle or declare it. 
```java=
public class Q3 {
    public static void main(String[] args) {
        System.out.println("Start ");
        try {
            int i = 1/0;
            System.out.println("Try ");
        } catch (Exception e){
            System.out.println("Catch ");
            // new exception in the catch block
            e = new Exception("My Exception");
            // need to handle or declare it
            throw e;

        } finally {
            System.out.println("Finally ");
        }
        System.out.println("After");
    }
}
```

### multi-catch 的陷井

multi-catch 中的 exception parameter 被自動宣告為 finally, 不可在 catch block 中 reassign.

*Multi-Catch clause*
A catch clause whose exception parameter is denoted as a union of types is called a multi-catch clause.

- An exception parameter of a multi-catch clause is implicitly declared final if it is not explicitly declared final.
- It is a compile-time error if a union of types contains two alternatives Di and Dj (i ≠ j) where Di is a subtype of Dj (§4.10.2).

Ref: https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-CatchType

## Ch12 JDBC

[Using RowSet Object | Java 8 Tutorial](https://docs.oracle.com/javase/tutorial/jdbc/basics/rowset.html)


## Ch15 Stream API

### 在 stream 中進行 group by 的動作

以 city 進行排序, 得到每個 city 下的不重覆的員工的 Last name

```java=
 Map<City, Set<String>> namesByCity =
    people
    .stream()
    .collect(
        Collectors.groupingBy(
            Person::getCity,
            Collectors.mapping(
                Person::getLastName, 
                toSet()
            )
        )
     );
```

[Collectors.mapping()](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#mapping-java.util.function.Function-java.util.stream.Collector-)

```java=
public static <T,U,A,R> Collector<T,?,R> mapping(
        Function<? super T,? extends U> mapper,
        Collector<? super U,A,R> downstream)
```

- `R` 是回傳後的資料型態, `U` 是 `R` 內的物件型態, 或者 `R<U>`


groupingBy 回傳的物件類別為 `Collector<T,?,Map<K,D>>`, 

[Collectors.groupingBy()](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#groupingBy-java.util.function.Function-java.util.stream.Collector-)

```java=
public static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(
        Function<? super T,? extends K> classifier,          
        Collector<? super T,A,D> downstream)
```

`downstream` 讓我們控制 `Map<K,D>` 中的 `D` 是那種物件型態.
也就是控制 map 中的 value 值是那種物件型態。

例如: 
```java=
//   使用 set 來裝每群的內容
// K: City, R: Set, T: People, U: String
 Map<City, Set<String>> namesByCity =
    people
    .stream()
    .collect( // Collect to Map<K, R<U>>
        Collectors.groupingBy(
            Person::getCity,  // K
            Collectors.mapping(
                Person::getLastName,  // T --> U
                toSet()                // Collect to R<U>
            )
        )
     );
//   使用 List 來裝每群的內容
Map<City, List<String>> namesByCity =
    people
    .stream()
    .collect(
        Collectors.groupingBy(
            Person::getCity,
            Collectors.mapping(
                Person::getLastName, 
                toList()
            )
        )
     );
```

### lambda expression x -> y -> x*y ?

Q25 的題目

```java=
public class Q25 {
    public static void main(String[] args) {
        IntStream stream = IntStream.of(10, 20, 30);
        // Line 1
        IntFunction<IntUnaryOperator> IF = (x) -> {
            return (y -> {
                return y * x;
            });
        };
        // Line 2
        IntStream newStream = stream.map(IF.apply(15));
        newStream.forEach(System.out::println);
    }
}
```

輸出結果爲何?

IF 為一個函數, 輸入值型態為 int, 輸出值型態為 `IntUnaryOperator`.

Line 2 中, `IF.apply(15)` 呼叫 `IntFunction` 的 `apply(x)`, 使得 x 的值為 15。之後，Unary Operator 成為:
```
  (y) -> y * 15
```

`stream.map()` 會呼叫此 Unary Operator 的 `applyAsInt(y)`, 其中 y 為 stream 中的原素。

所以, 此程式會將 stream 中的每一個元素值乘上 15。輸出結果為: 150, 300, 450.

### 2 種找出 List 最大值的方法

重要觀念:
1. stream.max() 回傳的資料型態為 `Optional<T>` 或者 `Optional{primitive_type}`, 例如 `OptionalInt`。
2. 若 stream 中的值不是 primitive type, 就不能直接呼叫無參數 max() 方法。呼叫 `max()` 時必須提供 Comparators 說明如何比較兩個物件。
3. 使用 `Comparators.comparing(Function<? super T,? extends U> keyExtractor)` 方法產生 Comparators。我們可以提供取出物件鍵值方法, 之後包裝成一個 Comparator, 再回傳。


```java=
public class Q26 {
    // Find the maximum value in the list
    public static void main(String[] args) {
        List<Integer> ints = Arrays.asList(11, 22, 8);
        // Method 1:
        // Comparator.comparing(Function_of_key_extractor)
        // 提供取出物件鍵值的方法, 並包裝成 Comparator
        Optional<Integer> max = ints.stream().max(Comparator.comparing(a -> a));
        System.out.println(max.get());
        
        // Method 2: 轉成 IntStream 後, 再呼叫 max()
        OptionalInt maxInt = ints.stream().mapToInt(a -> a.intValue()).max();
        System.out.println(maxInt.getAsInt());

    }
}
```