Save 37% off PRO during our Black Friday Sale! »

モダンなJavaの書き方

 モダンなJavaの書き方

2021.02.25
TECH Street
Javaエンジニア勉強会資料

F8bf7bb49653ecfdb66879ec19542641?s=128

Yuichi.Sakuraba

March 01, 2021
Tweet

Transcript

  1. モダンなJavaの書き方 Java in the Box 櫻庭 祐一

  2. Agenda Javaが変革する背景 Javaのトレンド では、どう書く?

  3. 自己紹介 • Java歴 26年 ◦ Java 1.0αから ◦ 2005年 Java

    Champion ◦ 2007年 JJUG創設メンバー • Client Side Java ◦ Java SE, JavaFX • 各種著作 ◦ Web+DB Press 連載 “見なおそう! モダンJavaの流儀” ◦ 書籍 Java SE 7/8 速攻入門
  4. Hardware Javaが変革する背景 Service/Application

  5. Hardware マルチコア Vector Computing/GPGPU 大量メモリ 超高速通信 Javaが変革する背景 Service/Application

  6. Hardware マルチコア Vector Computing/GPGPU 大量メモリ 超高速通信 Javaが変革する背景 Service/Application 巨大かつ複雑なシステム 頻繁な更新

  7. Hardware マルチコア Vector Computing/GPGPU 大量メモリ 超高速通信 Javaが変革する背景 Service/Application 巨大かつ複雑なシステム 頻繁な更新

    マイクロサービス コンテナ AI/ML
  8. Javaのトレンド 可読性の重視 関数の活用 Immutable

  9. Javaのトレンド 可読性の重視 関数の活用 Immutable var switch式 ラムダ式 ... Javaの機能

  10. Javaのトレンド 可読性の重視 関数の活用 Immutable var switch式 ラムダ式 ... ラムダ式 Stream

    API Flow (Reactive Stream) Javaの機能
  11. Javaのトレンド 可読性の重視 関数の活用 Immutable var switch式 ラムダ式 ... ラムダ式 Stream

    API Flow (Reactive Stream) Record Immutable Collection Factory Javaの機能
  12. Javaのトレンド 可読性の重視 関数の活用 Immutable var switch式 ラムダ式 ... ラムダ式 Stream

    API Flow (Reactive Stream) Record Immutable Collection Factory Javaの機能 Java 8 Java 11LTS Java 17LTS
  13. では、どう書く? • ラムダ式を自在に使えるようにする • オブジェクトの状態変化をなるべく避ける ◦ できればImmutableにする

  14. では、どう書く? • ラムダ式を自在に使えるようにする • オブジェクトの状態変化をなるべく避ける ◦ できればImmutableにする 可読性を向上させる Multithread Ready

    処理の切り分けを容易にする こう書くことで
  15. とりあえず、やってみよう 顧客クラス 顧客リストから製品IDごとの購買数のマップに変換する public class Customer { … // 購買履歴を製品IDのリストとして返す

    public List<Integer> getHistory() { … } }
  16. public Map<Integer, Long> convert(List<Customer> customers) { Map<Integer, Long> productCountMap =

    new HashMap<>(); for (int i = 0; i < customers.size(); i++) { Customer customer = customers.get(i); List<Integer> ids = customer.getHistory(); for (int j = 0; j < ids.size(); j++) { int pId = ids.get(j); Long productCount = productCountMap.get(pId); if (productCount == null) { productCountMap.put(pId, 1L); } else { productCount++; productCountMap.put(pId, productCount); } } } return productCountMap; } いにしえの書き方
  17. public Map<Integer, Long> convert(List<Customer> customers) { Map<Integer, Long> productCountMap =

    new HashMap<>(); for (int i = 0; i < customers.size(); i++) { Customer customer = customers.get(i); List<Integer> ids = customer.getHistory(); for (int j = 0; j < ids.size(); j++) { int pId = ids.get(j); Long productCount = productCountMap.get(pId); if (productCount == null) { productCountMap.put(pId, 1L); } else { productCount++; productCountMap.put(pId, productCount); } } } return productCountMap; } いにしえの書き方 ミュータブルなマップ ループ制御とロジックが混在 分かりにくいループカウンター NullPointerExceptionが発生するため オートボクシングができない
  18. public Map<Integer, Long> convert(List<Customer> customers) { Map<Integer, Long> productCountMap =

    new HashMap<>(); for (Customer customer: customers) { List<Integer> ids = customer.getHistory(); for (int pId: ids) { Long productCount = productCountMap.get(pId); if (productCount == null) { productCountMap.put(pId, 1L); } else { productCount++; productCountMap.put(pId, productCount); } } } return productCountMap; } Java 5だったら for-each文に変更
  19. public Map<Integer, Long> convert(List<Customer> customers) { Map<Integer, Long> productCountMap =

    customers.stream() .flatMap(customer -> customer.getHistory().stream()) .collect(Collectors.groupingBy(pId -> pId, Collectors.counting())); return productCountMap; } Java 8以降 マップの要素を変更しないので Immutableにすることも可能 2重ループの展開 トリッキーなif文の排除
  20. Conclusion • 可読性向上 • 関数の活用 • 状態変化を避けること • 新しい言語仕様/機能を積極的に試す を意識してコードを記述