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