Publicité

コレクションフレームワーク関連セッション(JavaOne & Devoxx報告会 2022 発表資料)

NTT DATA Technology & Innovation
15 Nov 2022
Publicité

Contenu connexe

Présentations pour vous(20)

Similaire à コレクションフレームワーク関連セッション(JavaOne & Devoxx報告会 2022 発表資料)(20)

Publicité

Plus de NTT DATA Technology & Innovation(20)

Dernier(20)

Publicité

コレクションフレームワーク関連セッション(JavaOne & Devoxx報告会 2022 発表資料)

  1. © 2022 NTT DATA Corporation コレクションフレームワーク関連セッション JavaOne & Devoxx報告会 2022 株式会社NTTデータ 阪田 浩一 2022年11月11日 • 想定視聴者: Javaのコレクションフレームワークのクラスを使ったことがあればどなたもOK!
  2. © 2022 NTT DATA Corporation 2 自己紹介 • 株式会社NTTデータ 所属 • JVMがとにかく好き • JavaOne 2015から毎回参加 • Javaチャンピオン • OpenJDK Author • 通算パッチ 10数個 • Oracle ACE Pro (Java分野) Koichi Sakata 阪田 浩一 jyukutyo
  3. © 2022 NTT DATA Corporation 3 このセッションで話すこと  コレクションフレームワークが関係する2セッション
  4. © 2022 NTT DATA Corporation 4 このセッションで話すこと  コレクションフレームワークが関係する2セッション • Sequenced Collections [LRN1422] • The Sincerest Form of Flattery [LRN1426]
  5. © 2022 NTT DATA Corporation 5 Sequenced Collections [LRN1422]
  6. © 2022 NTT DATA Corporation 6 JEP 431: Sequenced Collections  https://openjdk.org/jeps/431  順序ありのコレクションを定義するインタフェースを追加する
  7. © 2022 NTT DATA Corporation 7 JEP 431: Sequenced Collections  https://openjdk.org/jeps/431  順序ありのコレクションを定義するインタフェースを追加する  APIを2つ追加する • コレクションの最初、最後の要素を取得する統一的なAPI • 順序を逆にする統一的なAPI
  8. © 2022 NTT DATA Corporation 8 JEP 431: Sequenced Collections  https://openjdk.org/jeps/431  順序ありのコレクションを定義するインタフェースを追加する  APIを2つ追加する • コレクションの最初、最後の要素を取得する統一的なAPI • 順序を逆にする統一的なAPI  このJEPはCandidateステータスのため ドラフト実装をもとにディスカッション中 • https://github.com/openjdk/jdk/pull/7387
  9. © 2022 NTT DATA Corporation 9 スピーカー  Stuart Marksさん  Oracle社の方  このJEP 431のオーナー  IDEでのコードを使った説明のみのためスライドはなし • 記憶に加え JEPの記述とドラフトPRのコードを元にレポートします
  10. © 2022 NTT DATA Corporation 10 コレクションフレームワークの課題  順序ありコレクションとしてListとDequeがあるが 共通のインタフェースはCollectionで順序なしになる  順序ありのコレクションを表すのに この2つは具体的過ぎる
  11. © 2022 NTT DATA Corporation 11 コレクションフレームワークの課題  順序ありコレクションとしてListとDequeがあるが 共通のインタフェースはCollectionで順序なしになる  順序ありのコレクションを表すのに この2つは具体的過ぎる  Setを例に挙げると SetとHashSetは順序なし LinkedHashSetとSortedSetは順序あり 使いづらい わかりづらい 加えてunmodifiableSet()すると順序は失われる
  12. © 2022 NTT DATA Corporation 12 コレクションフレームワークの課題  順序ありコレクションとしてListとDequeがあるが 共通のインタフェースはCollectionで順序なしになる  順序ありのコレクションを表すのに この2つは具体的過ぎる  Setを例に挙げると SetとHashSetは順序なし LinkedHashSetとSortedSetは順序あり 使いづらい わかりづらい 加えてunmodifiableSet()すると順序は失われる  最初と最後の要素を取得する操作に統一性がない  降順(逆順)で反復する操作に統一性がない
  13. © 2022 NTT DATA Corporation 13 最初と最後の要素を取得する操作に統一性がない 型 最初の要素取得 最後の要素取得 List list.get(0) list.get(list.size()- 1) Deque deque.getFirst() deque.getLast() SortedSet sortedSet.first() sortedSet.last() LinkedHashSet linkedHashSet.iterator() .next() なし
  14. © 2022 NTT DATA Corporation 14 降順で反復する操作に統一性がない // NavigableSetだとdescendingSet()で降順のビューを取得できる for (var e : navSet.descendingSet()) process(e); // Dequeは降順イテレータが使える for (var it = deque.descendingIterator(); it.hasNext();) { var e = it.next(); process(e); } // ListだとListIteratorを使う for (var it = list.listIterator(list.size()); it.hasPrevious();) { var e = it.previous(); process(e); } // LinkedHashSetだと他のコレクションクラスにコピーするしかない
  15. © 2022 NTT DATA Corporation 15 降順で反復する操作に統一性がない // NavigableSetだとdescendingSet()で降順のビューを取得できる for (var e : navSet.descendingSet()) process(e); // Dequeは降順イテレータが使える for (var it = deque.descendingIterator(); it.hasNext();) { var e = it.next(); process(e); } // ListだとListIteratorを使う for (var it = list.listIterator(list.size()); it.hasPrevious();) { var e = it.previous(); process(e); } // LinkedHashSetだと他のコレクションクラスにコピーするしかない 加えてSetが返ってくるから stream()を呼んで Stream APIを使うことも IteratorからStream取得は Spliteratorsに渡して… と手間がかかる
  16. © 2022 NTT DATA Corporation 16 新しいインタフェースの導入 https://openjdk.org/jeps/431
  17. © 2022 NTT DATA Corporation 17 SequencedCollectionインタフェース interface SequencedCollection<E> extends Collection<E> { // 新規追加メソッド SequencedCollection<E> reversed(); // Dequeから昇格したメソッド void addFirst(E); void addLast(E); E getFirst(); E getLast(); E removeFirst(); E removeLast(); } set.reversed().stream() とできる
  18. © 2022 NTT DATA Corporation 18 SequencedSetインタフェース interface SequencedSet<E> extends Set<E>, SequencedCollection<E> { SequencedSet<E> reversed(); } // 比較のためSequencedCollectionインタフェースを再掲 interface SequencedCollection<E> extends Collection<E> { SequencedCollection<E> reversed(); } 共変戻り値でオーバーライド している
  19. © 2022 NTT DATA Corporation 19 SequencedMapインタフェース interface SequencedMap<K,V> extends Map<K,V> { // 新規追加メソッド SequencedMap<K,V> reversed(); SequencedSet<K> sequencedKeySet(); SequencedCollection<V> sequencedValues(); SequencedSet<Entry<K,V>> sequencedEntrySet(); V putFirst(K, V); V putLast(K, V); // SortedMapとNavigableMapから昇格したメソッド Entry<K, V> firstEntry(); Entry<K, V> lastEntry(); K firstKey(); K lastKey(); Entry<K, V> pollFirstEntry(); Entry<K, V> pollLastEntry(); }
  20. © 2022 NTT DATA Corporation 20 Collectionsクラスへの追加メソッド  static <T> SequencedCollection<T> unmodifiableSequencedCollection(SequencedCollection<? extends T> c)  static <T> SequencedSet<T> unmodifiableSequencedSet(SequencedSet<? extends T> s)  static <K,V> SequencedMap<K,V> unmodifiableSequencedMap(SequencedMap<? extends K, ? extends V> m)  戻り値の実際の型はUnmodifiableSequenced[Collection|Set|Map]となる
  21. © 2022 NTT DATA Corporation 21 ビルドすれば実際に試せます
  22. © 2022 NTT DATA Corporation 22 SequencedCollection#reversed()  戻り値は降順に並び替えた新しいコレクションではない  ReverseOrder...Viewクラスのインスタンスを返す • ReverseOrderListView、ReverseOrderSortedSetViewなど • 元のコレクションを内部に保持し 各操作を降順で扱う
  23. © 2022 NTT DATA Corporation 23 SequencedCollection#reversed()  戻り値は降順に並び替えた新しいコレクションではない  ReverseOrder...Viewクラスのインスタンスを返す • ReverseOrderListView、ReverseOrderSortedSetViewなど • 元のコレクションを内部に保持し 各操作を降順で扱う // 一部抜粋 class ReverseOrderListView<E> implements List<E> { final List<E> base; public E get(int i) { return base.get(base.size() - i - 1); } ... }
  24. © 2022 NTT DATA Corporation 24 SequencedCollection#reversed()  ReverseOrder...Viewクラスのインスタンスを返す • 元のコレクションを内部に保持し 各操作を降順で扱う • よって 元のコレクション 降順のコレクション どちらかを変更しても 両方とも変更したコレクションとなる // 一部抜粋 class ReverseOrderListView<E> implements List<E> { final List<E> base; public E get(int i) { return base.get(base.size() - i - 1); } ... }
  25. © 2022 NTT DATA Corporation 25 セッションの感想  現状はたしかに不便 一貫性がないと気づいた • Javaに慣れきってこうした側面が見えていない自分が見えた
  26. © 2022 NTT DATA Corporation 26 The Sincerest Form of Flattery [LRN1426]
  27. © 2022 NTT DATA Corporation 27 スピーカー  Maurice Naftalinさん  Javaチャンピオン  『Java Generics and Collections』(2006)の共著者  パターンマッチの部分のみJose Paumardさん
  28. © 2022 NTT DATA Corporation 28 セッションタイトルの謎 The Sincerest Form of Flattery (日本語訳) もっとも誠実なお世辞
  29. © 2022 NTT DATA Corporation 29 セッションの内容 Javaが関数型言語から学び追加した機能について Scalaと比較しながら確認する
  30. © 2022 NTT DATA Corporation 30 タイトルと内容がどう関連するのかわからなかった タイトル: The Sincerest Form of Flattery (日本語訳) もっとも誠実なお世辞 内容: Javaが関数型言語から学び追加した機能について Scalaと比較しながら確認する
  31. © 2022 NTT DATA Corporation 31 有名な文章の一部 “Imitation is the sincerest form of flattery that mediocrity can pay to greatness.” (日本語訳) 模倣は凡人が偉大さに対して送ることができる もっとも誠実なお世辞である ― オスカー・ワイルド
  32. © 2022 NTT DATA Corporation 32 セッションタイトルの謎解き 意地悪な視点でタイトルと内容を照合すると 凡庸な言語であるJavaによる 先を行っている言語としての関数型(Scala) の機能の 模倣についてのセッション
  33. © 2022 NTT DATA Corporation 33 関数型言語のエレガントで数学的にも正しい機能  高階関数 • Lisp 1958年  パラメータ多相 • ML 1975年  パターンマッチ • Caml 1985年 ただし実用的と言えないところもあった
  34. © 2022 NTT DATA Corporation 34 Pizza言語 Javaにこの3つの機能を加えたプログラミング言語  高階関数  パラメータ多相  パターンマッチ https://pizzacompiler.sourceforge.net/
  35. © 2022 NTT DATA Corporation 35 Pizzaコードでのパラメータ多相 class StoreSomething<A> { A something; StoreSomething(A something) { this.something = something; } A get() { return something; } } interface Set<A implements Comparable> { boolean contains(A x); Set<A> include(A x); }
  36. © 2022 NTT DATA Corporation 36 1997年ごろ https://dl.acm.org/doi/10.1145/263699.263715
  37. © 2022 NTT DATA Corporation 37 https://www.oreilly.com/library/view/java-generics-and/0596527756/
  38. © 2022 NTT DATA Corporation 38 PizzaからJavaのジェネリクスへ Pizza (1997) GJ: Generic Java (1998) Java 5 (2004) Scala (2003) https://homepages.inf.ed.ac.uk/wadler/gj/Documents/gj-tutorial.pdf
  39. © 2022 NTT DATA Corporation 39 GJからJava 5のジェネリクスへ  GJの時点でジェネリクスのほぼすべての機能があった • ワイルドカードを除く  1998年からJava 5の2004年まで なぜ6年かかったかは不明?とのこと • ワイルドカードの実装追加していたにせよ長い? http://www.bracha.org/wildcards.pdf
  40. © 2022 NTT DATA Corporation 40 ScalaとJavaでの取り組み方の違い  高階関数  パラメータ多相  パターンマッチ • Scalaはこれらの機能を一気に入れた (後方互換不要なのもある) • Javaは1つずつ入れている (後方互換性を保ちつつ) - 2004年にジェネリクス - 2014年にラムダ式 - パターンマッチは追加中
  41. © 2022 NTT DATA Corporation 41 セッション後半はそれぞれの詳細  ジェネリクス • erasure イレージャ • variance(変性): 共変や反変 • Scalaの場合  ラムダ式 • Javaで型システムを変更せずに関数を取り込むには • Scalaの場合  パターンマッチ • パターンとは • Scalaの場合
  42. © 2022 NTT DATA Corporation 42 本セッションでは時間のため1つだけ紹介  ジェネリクス • erasure イレージャ • variance(変性): 共変や反変 • Scalaの場合  ラムダ式 • Javaで型システムを変更せずに関数を取り込むには • Scalaの場合  パターンマッチ • パターンとは • Scalaの場合 ビギナーの方向けの 内容です
  43. © 2022 NTT DATA Corporation 43 Javaの配列は共変 // Arrays.sort(Object[] a)を考える Integer[] a = { 1, 2, 3 }; Arrays.sort(a); String[] b = { "Alice", "Bob", "Carol" }; Arrays.sort(b); // Integer配列型もString配列型もObject配列型のサブタイプ
  44. © 2022 NTT DATA Corporation 44 配列を共変にした結果
  45. © 2022 NTT DATA Corporation 45 ジェネリクスの設計方針  List<Integer>はList<Number>のサブタイプではない
  46. © 2022 NTT DATA Corporation 46 ジェネリクスの設計方針  境界型パラメータで共変サブタイピングを実現
  47. © 2022 NTT DATA Corporation 47 ジェネリクスの設計方針  ワイルドカードで反変サプタイピングを実現 • List<? super Number>はList<Number>のスーパータイプ 混乱した方は Effective Java 第3版 項目31を読んでみましょう
  48. © 2022 NTT DATA Corporation 48 Scalaの場合  変位指定アノテーションがある • [+A] [-A] [A]  たとえばScalaのリストはList[+A]で共変である abstract class Animal { def name: String } case class Cat(name: String) extends Animal case class Dog(name: String) extends Animal val cats: List[Cat] = List(Cat("Alice"), Cat("Bob")) val animals: List[Animal] = cats // OK
  49. © 2022 NTT DATA Corporation 49 セッションの感想  各機能の意味や使用方法は知っていても 歴史的経緯はあまり知らなかったので興味深かった  ジェネリクスについて機能面には習熟していても そのバックボーンについては知らないことが多いと気づいた
  50. © 2022 NTT DATA Corporation 本資料に記載されている会社名、商品名、又はサービス名は、各社の登録商標又は商標です。
Publicité