ホームページ  >  記事  >  Java  >  Java コレクション クラスのソース コードの Set の詳細な分析

Java コレクション クラスのソース コードの Set の詳細な分析

黄舟
黄舟オリジナル
2017-10-10 10:16:511600ブラウズ

次のエディターは、Java コレクション クラスのソース コード分析での Set の詳細な説明を提供します。編集者はこれがとても良いものだと思ったので、皆さんの参考として今から共有します。エディターに従って見てみましょう。List と同様に、Set コレクションは、HashSet や TreeSet などの Collection インターフェイスを継承します。 HashSet は HashMap を通じて実装され、TreeSet は TreeMap を通じて実装されるため、HashSet も TreeSet も独自のデータ構造を持たないことに注意してください。詳細は次のように要約できます。

• Set コレクション内の要素は繰り返すことができません。つまり、要素は一意です

•HashSet は要素のハッシュ値によって格納されるため、順序付けされておらず、最大 1 つの null オブジェクトが許可されます

•TreeSet は要素のサイズによって格納されるため、順序付けされます、そしてnull オブジェクトは許可されません

•Set Collection には get メソッドがないため、要素は反復子 (Iterators) を介してのみトラバースでき、ランダム アクセスは不可能です

1。HashSet1。 HashSet の実装方法を理解するために、HashSet のコードを以下に示します。


static final long serialVersionUID = -5024744406713321676L;

 private transient HashMap<E,Object> map;

 // Dummy value to associate with an Object in the backing Map
 private static final Object PRESENT = new Object();

ソースコードを観察すると、HashSet のデータは HashMap のインスタンス オブジェクト マップに格納されており、マップ内のキーに対応し、オブジェクト型参照 PRESENT は HashMap の値に対応するものであることがわかります。マップのダミー値には実際の意味はありません。 HashMap のいくつかの特徴 (不規則なストレージ、一意のキー値など) を考えると、重複できない Set コレクション要素の特性と HashSet の無秩序なストレージ特性を自然に理解できます。

ソースコードの観点から HashSet の基本的な使い方を理解しましょう:

•コンストラクター (4 種類) 1.HashSet() 空のコンストラクター、空の HashMap を初期化します

2。 HashSet(Collection2d4902c92e1e7bfd574f59708c57776a c) サブセット c を渡して HashMap を初期化します

3.HashSet(intInitialCapacity, floatloadFactor) 空の HashMap を初期化し、初期容量と負荷係数を指定します

4.HashSet(int InitialCapacity) 空のHashMapを初期化し、初期容量を指定します


public HashSet() {
  map = new HashMap<>();
 }

 public HashSet(Collection<? extends E> c) {
  map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
  addAll(c);
 }

 public HashSet(int initialCapacity, float loadFactor) {
  map = new HashMap<>(initialCapacity, loadFactor);
 }

 public HashSet(int initialCapacity) {
  map = new HashMap<>(initialCapacity);
 }

•要素を挿入します

1.add(E e) 指定された要素を挿入します(HashMapのputメソッドを呼び出すことで実装されます)

   Set<String> hashSet = new HashSet<String>();
   hashSet.add("D");
   hashSet.add("B");
   hashSet.add("C");
   hashSet.add("A");

•要素の検索

1.contains(Object o) セットに指定された要素が含まれているかどうかを判定する(HashMapのcontainsKeyメソッドを呼び出すことで実装される)

  public boolean contains(Object o) {
   return map.containsKey(o);
  }

2. get メソッドがないため、イテレーターを介して順次にトラバースすることしかできませんが、ランダムにアクセスすることはできません (HashMap の keySet のイテレーター実装を呼び出します)

  public Iterator<E> iterator() {
   return map.keySet().iterator();
  }

アプリケーション例:


Set<String> hashSet = new HashSet<String>();
  hashSet.add("D");
  hashSet.add("B");
  hashSet.add("C");
  hashSet.add("A");
  for (Iterator iterator = hashSet.iterator(); iterator.hasNext();) {
   String string = (String) iterator.next();
   System.out.print(string+" ");
  }//D A B C

• 要素を変更する

HashMapのキー値は変更できないため、HashSetは要素を変更できません

•要素の削除

1.remove(Object o) 指定された要素を削除します(実装するにはHashMapのremoveメソッドを呼び出します。戻り値はtrue または false)

  public boolean remove(Object o) {
   return map.remove(o)==PRESENT;
  }

2.clear() 要素をクリアします (実装するには HashMap の clear メソッドを呼び出します。戻り値はありません)


public void clear() {
   map.clear();
  }

2.TreeSetTreeSet はSortedSet 実装クラスの唯一のインターフェイス。前に述べたように、TreeSet は独自のデータ構造を持たず、TreeMap を通じて実装されます。そのため、TreeSet は赤と黒のバイナリ ツリーに基づいたストレージ構造でもあります。そのため、TreeSet は null オブジェクトを許可せず、順序 (デフォルトは昇順) で格納されます。 。

private transient NavigableMap<E,Object> m;
 
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();

上記ソースコードのNavigableMapはSrotedMapを継承したインターフェースであり、その実装クラスはTreeMapなのでTreeSet内のデータはTreeMapを介して格納されており、ここでのPRESENTも属性のない仮想値となります。実用的な意味。

ソースコードの観点から HashSet の基本的な使い方を理解しましょう:

•コンストラクター (4 種類) 1.TreeSet() 空のコンストラクター、空の TreeMap を初期化、デフォルトは昇順order

2.TreeSet(Comparator0d74ac1b2f8f9ab0eb66f930789a9645 comparator) は、降順の実装によく使用されるカスタム コンパレータを渡します

3.TreeSet(Collection2d4902c92e1e7bfd574f59708c57776a c) は、サブ Set c を渡します。 TreeMap オブジェクトの初期化に使用されます。デフォルトは昇順です

4.TreeSet(SortedSet1a4db2c2c2313771e5742b6debf617a1 s) は、サブセット コンパレータを使用して、TreeMap オブジェクトの初期化に使用される、順序付きサブセット s を渡します


public TreeSet() {
  this(new TreeMap<E,Object>());
 }

 public TreeSet(Comparator<? super E> comparator) {
  this(new TreeMap<>(comparator));
 }

 public TreeSet(Collection<? extends E> c) {
  this();
  addAll(c);
 }

 public TreeSet(SortedSet<E> s) {
  this(s.comparator());
  addAll(s);
 }

アプリケーション例

//自定义一个比较器,实现降序排列
  Set<Integer> treeSet = new TreeSet<Integer>(new Comparator<Integer>() {

   @Override
   public int compare(Integer o1, Integer o2) {
//    return 0;  //默认升序
    return o2.compareTo(o1);//降序
   }
  });
  treeSet.add(200);
  treeSet.add(120);
  treeSet.add(150);
  treeSet.add(110);
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  } //200 150 120 110

ArrayList<Integer> list = new ArrayList<Integer>();
  list.add(300);
  list.add(120);
  list.add(100);
  list.add(150);
  System.out.println(list); //[300, 120, 100, 150]
  
  //传入一个子集,默认升序排列
  TreeSet<Integer> treeSet = new TreeSet<Integer>(list);
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  }//100 120 150 300

/*
   * 传入一个有序的子集,采用子集的比较器
   *  注意子集的类型必须是SortedSet及其子类或者实现类,否则将采用默认的比较器
   *  所以此处subSet的类型也可以是TreeSet。
   */
  
  SortedSet<Integer> subSet = new TreeSet<Integer>(new Comparator<Integer>() {

   @Override
   public int compare(Integer o1, Integer o2) {
//    return 0;  //默认升序
    return o2.compareTo(o1);//降序
   }
  });
  subSet.add(200);
  subSet.add(120);
  subSet.add(150);
  subSet.add(110);
  for (Iterator iterator = subSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  } //200 150 120 110 
  
  System.out.println();
  Set<Integer> treeSet = new TreeSet<Integer>(subSet);
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  }//200 150 120 110 
  
  System.out.println();
  treeSet.add(500);
  treeSet.add(100);
  treeSet.add(105);
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  }//500 200 150 120 110 105 100

• 要素の挿入

1.add(E e) 指定された要素を挿入(TreeMapのputメソッドの呼び出しで実装)

2.addAll( Collection


ArrayList<Integer> list = new ArrayList<Integer>();
  list.add(300);
  list.add(120);
  list.add(100);
  list.add(150);
  System.out.println(list); //[300, 120, 100, 150]
  
  Set<Integer> treeSet = new TreeSet<Integer>();
  
  //插入一个子集,默认升序
  treeSet.addAll(list);
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  }//100 120 150 300

•要素を検索します

1.contains(Object o) コレクションに指定されたオブジェクトが含まれているかどうかを判断します (TreeMap の containsKey メソッドを呼び出すことで実装されます)。

2.与HashSet一样,TreeSet的实现类中没有get方法,所以只能通过迭代器依次遍历,而不能随机访问(调用TreeMap中keySet的迭代器实现)。

•修改元素

TreeSet不能进行修改元素的操作,原因与HashSet一样。

•删除元素

1.remove(Object o) 删除指定元素(调用TreeMap中的remove方法实现,返回true或者false)


  public boolean remove(Object o) {
   return m.remove(o)==PRESENT;
  }

2.clear() 清空元素(调用TreeMap中的clear方法实现,无返回值)


  public void clear() {
   m.clear();
  }

应用示例:


ArrayList<Integer> list = new ArrayList<Integer>();
  list.add(300);
  list.add(120);
  list.add(100);
  list.add(150);
  System.out.println(list); //[300, 120, 100, 150]
  
  Set<Integer> treeSet = new TreeSet<Integer>();
  
  //插入一个子集,默认升序
  treeSet.addAll(list);
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  }//100 120 150 300 
  
  System.out.println(treeSet.remove(100));//true
  for (Iterator iterator = treeSet.iterator(); iterator.hasNext();) {
   Integer integer = (Integer) iterator.next();
   System.out.print(integer+" ");
  }//120 150 300 
  
  treeSet.clear();
  System.out.println(treeSet.size());//0

至此,HashSet和TreeSet的存储结构及基本用法介绍完毕。

以上がJava コレクション クラスのソース コードの Set の詳細な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。