これが最良の設計選択ではなかったことは間違いありません。
要約する:
HashSet には 3 つのコンストラクターがあります。
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* the specified initial capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
/**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* the specified initial capacity and default load factor (0.75).
*
* @param initialCapacity the initial capacity of the hash table
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
/**
* Constructs a new, empty linked hash set. (This package private
* constructor is only used by LinkedHashSet.) The backing
* HashMap instance is a LinkedHashMap with the specified initial
* capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @param dummy ignored (distinguishes this
* constructor from other int, float constructor.)
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
最後のものには、使用されない追加のパラメーター ダミーがあり、コンパイラーが同じパラメーターを持つ 2 つのコンストラクターを区別できるようにするためだけに存在します。唯一の違いは、バッキング マップの実装を変更することです。
これらのクラスが作成されて以来、私たちはオブジェクトの設計を大幅に改善しました。
これが今日書き直された場合、MapMap 実装をバッキング ストアとして使用できるように、代わりに を使用するコンストラクターがおそらく存在するでしょう。
HashSet(Map<K,V> backingMap);
および/または、名前は異なるが同じパラメーターを持つ複数の静的ファクトリメソッドが存在する可能性があります
public static HashSet create(int initialCapacity, float loadFactor)
public static HashSet createLinked(int initialCapacity, float loadFactor)
編集
JB Nizet は興味深い点を指摘しています。HashSet のreadObject()メソッドには、ObjectInputStream からオブジェクトを再構築して「これ」のインスタンスが LinkedHashSet のものかどうかを確認する際の明示的なコードがあります。
// Create backing HashMap
map = (((HashSet<?>)this) instanceof LinkedHashSet ?
new LinkedHashMap<E,Object>(capacity, loadFactor) :
new HashMap<E,Object>(capacity, loadFactor));
これは、コンストラクターのダミー パラメーター バージョンがパッケージ プライベートであるため、実際にのみ可能であり、現在可能な実装は 2 つだけです。この手法がないと、ReadObject() を正しく使用できません。
これがおそらく、Josh Bloch が『Effective Java』のシリアライゼーションの章を書いた理由です。LinkedHashSet を正しく読み取るには、おそらく SerializationProxy (項目 78) を使用する必要があります。