HashSetを深く理解する
43035 ワード
文書ディレクトリ HashSetとは? HashSetの継承クラスと実装インタフェースはどれらがありますか? HashSetの主要メンバー変数 HashSetのコンストラクション関数 一、HashSet() 二、HashSet(Collection extends E>c) 三、HashSet(int initialCapacity,float loadFactor) 四、HashSet(int initialCapacity) 五、HashSet(int initialCapacity,float loadFactor,boolean dummy) HashSetでよく使われる方法は何ですか? isEmpty() contains(Object o) add(E e) remove(Object o) iterator() keySet() size() clear() まとめ なぜHashSetは重複値を許可しないのですか? HashSetはnull要素として保存できますか? HashSetはいったい秩序があるのか、それとも無秩序なのか. HashSetはスレッドが安全ですか? HashSetから指定された要素を取得するにはどうすればいいですか?
ハシュセットって何?
HashSetはjavaが存在する.utilパッケージのクラスは、Javaでよく使われる集合クラスであり、Setインタフェースの実装クラスであり、このコンテナに重複するオブジェクトを格納できない.HashSetではHashMapに基づいて実装されており、下位層ではHashMapを使用して要素を格納しています.HashMapに関する記事はここを参照してください.
HashSetの継承クラスと実装のインタフェースはどれらがありますか?
HashSetはAbstractSetクラスを継承し、Set、Cloneable、Serializableインタフェースを実装していることが上記のコードから分かる
HashSetの主要メンバー変数
HashSetのコンストラクション関数
一、HashSet()
無参のHashSet()
二、HashSet(Collection extends E>c)
三、HashSet(int initialCapacity,float loadFactor)
HashMapの友达を深く理解したことがあると信じています.ここを見て、知り合いのような感じがしますか?そう、HashMapのinitialCapacityとloadFactorです
四、HashSet(int initialCapacity)
五、HashSet(int initialCapacity,float loadFactor,boolean dummy)
HashSetでよく使われる方法は何ですか?
isEmpty()
コレクションに要素が含まれていない場合はtrueを返します.
contains(Object o)
containsは、HashSetに指定された要素が含まれているかどうかを判断し、ある場合はtrueを返します.
add(E e)
既存の要素をHashSetに追加すると、新しく追加した集合要素はHashMapに保存されず、元の要素も変更されません.つまり、HashSetに重複する要素の特性がないことを示します.
add()メソッドのput操作は実際にはHashMapのput操作であり,put操作はputValを返す.
hash()とputVal()メソッドの詳細については、ここをクリックしてHashMapを深く理解してください.ここでは説明しません.
説明:HashSetが入れる値は毎回keyとして扱われ、HashMapのput()メソッドでは一方向チェーンテーブルを遍歴する形で、同じkeyと同じkeyで生成されたhash値に対して、指定した値で古い値を置き換えることができます
remove(Object o)
指定した要素がsetに存在する場合、削除
iterator()
上のコードでは、HashSetの要素が最下位のHashMapのkeyに格納されていることがわかります.keySetが遍歴していることがわかります.HashMapのkeyキーが重複していると、その値が更新され、keyが重複しないことが保証されます.つまり、HashSetが追加した値は重複しません.
keySet()
size()
コレクション内の要素の数を返します.
clear()
HashMapを呼び出すclear()メソッドNodeのすべてのノードをクリア
まとめ
なぜHashSetは重複値を許さないのですか?
setは線形構造であり、setの値は繰り返すことができず、hashsetはsetのhash実装である.HashSetの内部はHashMapのkeyを用いて要素を格納しているからである.
出力:
set ------ [hello] list ------ [hello, hello]
もう一つ例を挙げる
出力:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
出力内容により、20以内の数字100個に重複がないことがわかります
HashSetはnull要素として保存できますか?
はい、HashSetの下位層はHashMapによって実現されるので、HashMapはkeyがnullであることを許可するので、HashSetはもちろん
出力:null
HashSetは秩序あるのか無秩序なのか.
HashSetは無秩序であり、HashMapのkeyは無秩序であり、HashSetの下位実装はHashMapであるため、HashSetは無秩序である
秩序と無秩序はどのように理解しますか?
答え:挿入内容の順序が出力内容の順序と一致している場合は秩序があり、そうでない場合は無秩序である
上の例をとって検討を続ける
出力:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
誰?誰が無秩序だと言ったの?これは明らかに秩序があるのではないでしょうか.執着しているあなたたちもきっとおかしいと思います.metoo、OK、検討を続けます.
もう一つの例を見てみましょう
出力:
1 2 3 4 5
まだ秩序があるのか、いったいどうしたのか.
わざと数字の位置を変えてみる
出力:
1 2 3 4 5
OK、今度は無秩序だから、もう一つやってみよう
出力:
1 2 3 4 5
はい、無秩序に来ました.
では、最初の例はどういうことですか.以下に説明します.
説明:作成したHashSetはIntegerタイプであるため、これも最も偶然な点です.IntegerタイプhashCode()の戻り値はint値自体であり、格納時に要素がいくつかの演算によって配列内の位置が得られます.このステップでは、それ自体がダウンスケール(このステップのみを考慮)であるため、実はソート機能が実現されており、intタイプの範囲が広すぎてメモリが置けないため、それを型取り演算し、ハッシュ競合を減らすため、また型取り前に、摂動関数の計算を行い、得られた数を要素ダウンスケールとしてJDK 8でのhashアルゴリズムに従い、これにより、HashMapのhash()演算後もデータは自分自身の値であり、ハッシュ競合は発生しない
まとめ:だからHashSetはただ秩序を保証しないだけで、無秩序を保証するわけではありません
HashSetはスレッドが安全ですか?
いいえ、HashSetはスレッドが安全ではありません.
HashSetから指定した要素を取得するにはどうすればいいですか?
SetコレクションをListリストに変換することでgetアクションを使用して指定した要素を取得できます
出力:
2 java.util.ArrayList
ハシュセットって何?
HashSetはjavaが存在する.utilパッケージのクラスは、Javaでよく使われる集合クラスであり、Setインタフェースの実装クラスであり、このコンテナに重複するオブジェクトを格納できない.HashSetではHashMapに基づいて実装されており、下位層ではHashMapを使用して要素を格納しています.HashMapに関する記事はここを参照してください.
HashSetの継承クラスと実装のインタフェースはどれらがありますか?
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
}
HashSetはAbstractSetクラスを継承し、Set、Cloneable、Serializableインタフェースを実装していることが上記のコードから分かる
HashSetの主要メンバー変数
// ID
static final long serialVersionUID = -5024744406713321676L;
// HashSet HashMap
private transient HashMap<E,Object> map;
// , value map
private static final Object PRESENT = new Object();
HashSetのコンストラクション関数
一、HashSet()
無参のHashSet()
// , HashMap
public HashSet() {
//
map = new HashMap<>();
}
二、HashSet(Collection extends E>c)
// Set
public HashSet(Collection<? extends E> c) {
// Map
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
三、HashSet(int initialCapacity,float loadFactor)
HashMapの友达を深く理解したことがあると信じています.ここを見て、知り合いのような感じがしますか?そう、HashMapのinitialCapacityとloadFactorです
//
public HashSet(int initialCapacity, float loadFactor) {
// initialCapacity( HashMap ), loadFactor( HashMap )
map = new HashMap<>(initialCapacity, loadFactor);
}
四、HashSet(int initialCapacity)
// HashSet
public HashSet(int initialCapacity) {
// initialCapacity HashMap
map = new HashMap<>(initialCapacity);
}
五、HashSet(int initialCapacity,float loadFactor,boolean dummy)
//
// initialCapacity:
// loadFactor:
// dummy:
// public , LinkedHashSet
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
// LinkedHashMap
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
HashSetでよく使われる方法は何ですか?
isEmpty()
コレクションに要素が含まれていない場合はtrueを返します.
public boolean isEmpty() {
// HashMap isEmpty HashSet
return map.isEmpty();
}
contains(Object o)
containsは、HashSetに指定された要素が含まれているかどうかを判断し、ある場合はtrueを返します.
public boolean contains(Object o) {
// HashMap containsKey key, true
return map.containsKey(o);
}
add(E e)
既存の要素をHashSetに追加すると、新しく追加した集合要素はHashMapに保存されず、元の要素も変更されません.つまり、HashSetに重複する要素の特性がないことを示します.
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
add()メソッドのput操作は実際にはHashMapのput操作であり,put操作はputValを返す.
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
hash()とputVal()メソッドの詳細については、ここをクリックしてHashMapを深く理解してください.ここでは説明しません.
説明:HashSetが入れる値は毎回keyとして扱われ、HashMapのput()メソッドでは一方向チェーンテーブルを遍歴する形で、同じkeyと同じkeyで生成されたhash値に対して、指定した値で古い値を置き換えることができます
remove(Object o)
指定した要素がsetに存在する場合、削除
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
iterator()
// HashSet ,
public Iterator<E> iterator() {
// HashMap keySet key
return map.keySet().iterator();
}
上のコードでは、HashSetの要素が最下位のHashMapのkeyに格納されていることがわかります.keySetが遍歴していることがわかります.HashMapのkeyキーが重複していると、その値が更新され、keyが重複しないことが保証されます.つまり、HashSetが追加した値は重複しません.
keySet()
public Set<K> keySet() {
// AbstractMap keySet;
Set<K> ks = keySet;
// key
if (ks == null) {
// keySet
ks = new KeySet();
//
keySet = ks;
}
return ks;
}
size()
コレクション内の要素の数を返します.
public int size() {
return map.size();
}
clear()
HashMapを呼び出すclear()メソッドNodeのすべてのノードをクリア
public void clear() {
map.clear();
}
まとめ
なぜHashSetは重複値を許さないのですか?
setは線形構造であり、setの値は繰り返すことができず、hashsetはsetのhash実装である.HashSetの内部はHashMapのkeyを用いて要素を格納しているからである.
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("hello");
set.add("hello");
System.out.println("set ------- " + set);
List<String> list = new ArrayList<>();
list.add("hello");
list.add("hello");
System.out.println("list ------ " + list);
}
}
出力:
set ------ [hello] list ------ [hello, hello]
もう一つ例を挙げる
public class HashSetDemo {
public static void main(String[] args) {
Random random = new Random();
Set<Integer> set = new HashSet<>();
// 100 20
for (int i = 0; i < 100; i++) {
// set
set.add(random.nextInt(20));
}
System.out.println(set);
}
}
出力:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
出力内容により、20以内の数字100個に重複がないことがわかります
HashSetはnull要素として保存できますか?
はい、HashSetの下位層はHashMapによって実現されるので、HashMapはkeyがnullであることを許可するので、HashSetはもちろん
public class HashSetDemo {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add(null);
System.out.println(set);
}
}
出力:null
HashSetは秩序あるのか無秩序なのか.
HashSetは無秩序であり、HashMapのkeyは無秩序であり、HashSetの下位実装はHashMapであるため、HashSetは無秩序である
秩序と無秩序はどのように理解しますか?
答え:挿入内容の順序が出力内容の順序と一致している場合は秩序があり、そうでない場合は無秩序である
上の例をとって検討を続ける
public class HashSetDemo {
public static void main(String[] args) {
Random random = new Random();
Set<Integer> set = new HashSet<>();
for (int i = 0; i < 100; i++) {
set.add(random.nextInt(20));
}
System.out.println(set);
}
}
出力:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
誰?誰が無秩序だと言ったの?これは明らかに秩序があるのではないでしょうか.執着しているあなたたちもきっとおかしいと思います.metoo、OK、検討を続けます.
もう一つの例を見てみましょう
public class HashSetDemo {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
for (Integer integer : set) {
System.out.print(integer + " ");
}
}
}
出力:
1 2 3 4 5
まだ秩序があるのか、いったいどうしたのか.
わざと数字の位置を変えてみる
public class HashSetDemo {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(3);
set.add(2);
set.add(4);
set.add(5);
for (Integer integer : set) {
System.out.print(integer + " ");
}
}
}
出力:
1 2 3 4 5
OK、今度は無秩序だから、もう一つやってみよう
public class HashSetDemo {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(5);
set.add(4);
set.add(3);
set.add(2);
set.add(1);
for (Integer integer : set) {
System.out.print(integer + " ");
}
}
}
出力:
1 2 3 4 5
はい、無秩序に来ました.
では、最初の例はどういうことですか.以下に説明します.
説明:作成したHashSetはIntegerタイプであるため、これも最も偶然な点です.IntegerタイプhashCode()の戻り値はint値自体であり、格納時に要素がいくつかの演算によって配列内の位置が得られます.このステップでは、それ自体がダウンスケール(このステップのみを考慮)であるため、実はソート機能が実現されており、intタイプの範囲が広すぎてメモリが置けないため、それを型取り演算し、ハッシュ競合を減らすため、また型取り前に、摂動関数の計算を行い、得られた数を要素ダウンスケールとしてJDK 8でのhashアルゴリズムに従い、これにより、HashMapのhash()演算後もデータは自分自身の値であり、ハッシュ競合は発生しない
まとめ:だからHashSetはただ秩序を保証しないだけで、無秩序を保証するわけではありません
HashSetはスレッドが安全ですか?
いいえ、HashSetはスレッドが安全ではありません.
HashSetから指定した要素を取得するにはどうすればいいですか?
SetコレクションをListリストに変換することでgetアクションを使用して指定した要素を取得できます
public class HashSetDemo {
//
public static String getType(Object obj) {
return obj.getClass().getName().toString();
}
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
List<Integer> list = new ArrayList<>(set);
System.out.println(list.get(1)); //
System.out.println(getType(list)); //
}
}
出力:
2 java.util.ArrayList