Javaのコレクションフレームワークまとめ

スポンサーリンク

Javaのスレッドセーフなコレクションについて調べてみたら、複雑過ぎて頭がクラクラしてきた。
けど、まとめていく過程で自分なりに理解できた気がする。
各クラスのメソッドについてはあまり記載してない。

f:id:sato_susumu:20170913202638j:plain

レガシークラス

古いクラスなので基本は使わない。

レガシークラス 対応するクラス
Vector ArrayList
Stack LinkedList
HashTable HashMap

コレクション インタフェース

java.util直下のインタフェース

インタフェース 説明 補足
java.util.List リスト 順序付けされたコレクション
java.util.Queue キュー JavaではFIFOとは限らない。
java.util.Deque 両端キュー デックと読む。デキューではない。Double Ended Queueの略。
java.util.Set セット 重複した要素を許可しないコレクション
java.util.Map マップ キーと値のペアを扱うコレクション
java.util.SortedSet キー順にソートされたSet Setのサブインタフェース
java.util.SortedMap キー順にソートされたMap Mapのサブインタフェース
java.util.NavigableSet 指定したキーに近い内容を取得することができるSet SortedSetのサブインタフェース
java.util.NavigableMap 指定したキーに近い内容を取得することができるMap SortedMapのサブインタフェース

java.util.concurrent.BlockingQueue

Queueのサブインターフェース。
BlockingQueueの実装は容量を制限している場合がある。

BlockingQueueのメソッドのサマリー

例外のスロー 特殊な値 ブロック タイム・アウト
挿入 add(e) offer(e) put(e) offer(e, time, unit)
削除 remove() poll() take() poll(time, unit)
検査 element() peek() 適用外 適用外

BlockingQueue (Java Platform SE 8) より

  • add(e), remove(), element()は処理できないと例外発生する
  • offer(e)
    要素追加。容量が空いてなければfalseを返す。
  • put(e)
    要素追加。容量が空いてなければ待機。
  • poll()
    キューの先頭を取得して削除。キューが空の場合はnullを返す。
  • take()
    キューの先頭を取得して削除。必要に応じて、要素が利用可能になるまで待機。
  • peek()
    キューの先頭を取得するが、削除しない。キューが空の場合はnullを返す。

java.util.concurrent.BlockingDeque

BlockingQueueのサブインターフェース。
両端キュー

java.util.concurrent.TransferQueue (1.7)

BlockingQueueのサブインターフェース。

java.util.concurrent.ConcurrentMap

スレッドの安全性と原子性の保証を提供するMapです。

java.util.concurrent.ConcurrentSetはない

java.util.concurrent.ConcurrentNavigableMap

NavigableMapオペレーションをサポートするConcurrentMap。
指定した値にもっとも近い内容を取得することができる

java.util.concurrent.ConcurrentNavigableSetはない

同期化、並列化されていないコレクション実装

  • java.util」の直下に所属するコレクションの実装
  • スレッドセーフではない
  • イテレート中に(主に別スレッドで)操作を行った場合、ConcurrentModificationException が投げられる。
    toStringなど、内部でイテレート処理が走ることがあるので注意。
インタフェース ハッシュ表 サイズ変更可能な配列 バランス・ツリー リンク・リスト ハッシュ表+リンク・リスト
Set HashSet TreeSet LinkedHashSet
List ArrayList LinkedList
Deque ArrayDeque LinkedList
Map HashMap TreeMap LinkedHashMap

Collections Frameworkの概要 より

java.util直下の実装
クラス名 補足
java.util.ArrayList 配列実装List
java.util.LinkedList リンクノードに基づくList。List、Queue、Dequeインタフェースを実装
java.util.HashSet ハッシュテーブル実装Set
java.util.HashMap ハッシュテーブル実装Map
java.util.TreeSet バランスツリー実装のSet。NavigableSetを実装。
java.util.TreeMap バランスツリー実装Map NavigableMapを実装。
java.util.PriorityQueue 同期化されてないので注意。|スレッドセーフである必要が有る場合はPriorityBlockingQueueクラスを使用。

同期化コレクション

  • Vector」や「Hashtable」や「Collections.synchronizedXXX()による同期化ラッパー」のこと。
  • 要素の内容の変更があるようなメソッドは、全てsynchronizedになっているのが特徴。
  • 同期コレクションはロックによりコレクションの操作を1スレッドに限定
  • イテレート中に操作を行った場合、ConcurrentModificationException が投げられるのはラッパー使用前と同様。

java.util.Collections.synchronizedXXX()による同期化ラッパー

指定されたコレクションに連動する同期(スレッドセーフな)コレクションを返す。

例:

List<String> list = Collections.synchronizedList(new ArrayList<String>());  
Set<String> set = Collections.synchronizedSet(new HashSet<String>());  
Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());  

並行コレクション(並列コレクション)

  • 「CopyOnWriteArrayList」や「ConcurrentHashMap」などJavaSE5.0より加わった「java.util.concurrent」以下にあるコレクションのこと。
  • マルチスレッドから同時操作できるように設計
  • 複合アクションに対応している。
  • イテレーション時にConcurrentModificationExceptionを発生させない。

CopyOnWriteArrayList

Copy-on-Write実装によるスレッドセーフList

Listの変更があった場合、新たなコピーを作成。
これによりアクセス時の同期が不要なる。
イテレート処理はイテレータが作られた時の状態で走査され、別スレッドからの変更の影響は受けない。

CopyOnWriteArraySet

Copy-on-Write実装によるスレッドセーフSet

ConcurrentHashMap

並行ハッシュテーブル実装によるMap

ConcurrentHashSetはない

ConcurrentHashMap.KeySetViewメソッドを使う。

ConcurrentSkipListMap

ConcurrentNavigableMapを実装したMap。
指定した値に近いキーを拾ってくることもできる。

ConcurrentSkipListSet

NavigableSetを実装したSet。
指定した値に近いキーを拾ってくることもできる。

キュー関連のまとめ

注意:容量指定がなくてもメモリがなければ例外は発生する。

クラス 方向 容量制限 ブロッキング 主な実装インタフェース
ArrayBlockingQueue FIFO あり ブロッキング BlockingQueue
LinkedBlockingQueue FIFO 任意 ブロッキング BlockingQueue
PriorityBlockingQueue 優先順位付きFIFO なし ブロッキング BlockingQueue
DelayQueue FIFO なし ブロッキング BlockingQueue
SynchronousQueue FIFO - ブロッキング BlockingQueue
LinkedBlockingDeque 双方向 任意 ブロッキング BlockingDeque
ConcurrentLinkedQueue FIFO なし ノンブロッキング Queue
LinkedTransferQueue FIFO なし ブロッキング or ノンブロッキング両方 TransferQueue

ArrayBlockingQueue

生成時に容量を指定。

LinkedBlockingQueue

生成時に容量を指定しても、しなくてもいい。

PriorityBlockingQueue

DelayQueue

遅延時間が経過後にのみ、要素を取得できる。

SynchronousQueue

値の追加は、値の取得が行われるまでブロックする。
値の取得は、値の追加が行われるまでブロックする。

  • 同期キューには、内部容量がまったくありません。
  • 要素が存在するのは削除しようとするときだけなので、同期キューで peek を実行することはできません。
  • 別のスレッドが削除を試みていないかぎり、どのメソッドを使用しても要素を挿入することはできません。
  • 反復するものが存在しないため、反復は実行できません。

LinkedBlockingDeque

生成時に容量を指定しても、しなくてもいい。

ConcurrentLinkedQueue

ノンブロッキング

LinkedTransferQueue (1.7)

ブロッキング、ノンブロッキング両方。

参考

Java並行・並列・非同期処理チートシート - Qiita

並列コレクションを使う | Java好き

java.util.concurrent (Java Platform SE 7 )

Java新機能メモ(Hishidama's Java up-to-date)