Der folgende Editor bietet Ihnen eine detaillierte Erklärung der Quellcodeanalyse der Set-in-Java-Collection-Klasse. Der Herausgeber findet es ziemlich gut, deshalb werde ich es jetzt mit Ihnen teilen und es allen als Referenz geben. Folgen wir dem Editor, um einen Blick darauf zu werfen
Set-Sammlung erbt wie List von der Collection-Schnittstelle. Zu den häufig verwendeten Implementierungsklassen gehören HashSet und TreeSet. Es ist erwähnenswert, dass HashSet über HashMap und TreeSet über TreeMap implementiert wird, sodass weder HashSet noch TreeSet über eine eigene Datenstruktur verfügen. Die Details können wie folgt zusammengefasst werden:
• Die Elemente in der Set-Sammlung können nicht Wiederholen, das heißt, die Elemente sind eindeutig
•HashSet wird durch den Hashwert des Elements gespeichert, ist also ungeordnet und lässt höchstens ein Nullobjekt zu
•TreeSet wird durch gespeichert die Größe des Elements, also ist es geordnet, und Nullobjekte sind nicht erlaubt
• Die Set-Sammlung verfügt über keine Get-Methode, daher können die Elemente nur über Iteratoren (Iterator) und Direktzugriff durchlaufen werden ist nicht möglich
1 .HashSet
Ein Teil des Quellcodes von HashSet wird unten angegeben, um seine Implementierung zu verstehen.
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();
Wenn wir den Quellcode betrachten, wissen wir, dass die Daten von HashSet in der Instanzobjektkarte von HashMap gespeichert sind und dem Schlüssel in entsprechen Karte und Objekt Die Typreferenz PRESENT ist ein virtueller Wert, der dem Wert in der Karte entspricht und keine praktische Bedeutung hat. Wenn wir an einige Merkmale von HashMap denken: ungeordneter Speicher, eindeutiger Schlüsselwert usw., können wir natürlich die Merkmale nicht wiederholbarer Set-Sammlungselemente und die ungeordneten Speichermerkmale von HashSet verstehen.
Das Folgende ist ein Verständnis der grundlegenden Verwendung von HashSet aus der Perspektive des Quellcodes:
•Konstruktor (vier Typen)
1.HashSet() Leerer Konstruktor, initialisiert eine leere HashMap
2.HashSet(Collection erweitert E> c) Übergeben Sie eine Teilmenge c, wird zum Initialisieren von HashMap verwendet
3.HashSet(int initialCapacity, float loadFactor) Initialisiert eine leere HashMap und gibt die anfängliche Kapazität und den Ladefaktor an
4.HashSet(int initialCapacity) Initialisiert eine leere HashMap und geben Sie die Anfangskapazität an
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); }
• Element einfügen
1.add(E e ) Fügen Sie das angegebene Element ein (implementiert durch Aufrufen der Put-Methode von HashMap)
Set<String> hashSet = new HashSet<String>(); hashSet.add("D"); hashSet.add("B"); hashSet.add("C"); hashSet.add("A");
•Finden Sie das Element
1. enthält(Objekt o) Bestimmen Sie, ob die Menge das angegebene Element enthält (implementiert durch Aufrufen der Methode „containsKey“ von HashMap)
public boolean contains(Object o) { return map.containsKey(o); }
2 Da es keine Get-Methode gibt die Implementierungsklasse von HashSet, also nur Kann sequentiell durch Iteratoren durchlaufen werden, aber nicht zufällig darauf zugegriffen werden (Aufruf der Iterator-Implementierung von keySet in HashMap)
public Iterator<E> iterator() { return map.keySet().iterator(); }
Anwendungsbeispiel :
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
•Elemente ändern
Da der Schlüsselwert in HashMap nicht geändert werden kann, kann HashSet nicht geändert werden elements
•Element löschen
1.remove(Object o) Löscht das angegebene Element (implementiert durch Aufrufen der Remove-Methode in HashMap, der Rückgabewert ist true oder false )
public boolean remove(Object o) { return map.remove(o)==PRESENT; }
2.clear() Löscht das Element (implementiert durch Aufruf der Clear-Methode in HashMap, kein Rückgabewert)
public void clear() { map.clear(); }
2.TreeSet
TreeSet ist die einzige Implementierungsklasse der SortedSet-Schnittstelle. Wie bereits erwähnt, verfügt TreeSet nicht über eine eigene Datenstruktur, sondern wird über TreeMap implementiert. Daher ist TreeSet auch eine Speicherstruktur, die auf roten und schwarzen Binärbäumen basiert. Daher lässt TreeSet keine Nullobjekte zu und wird in der richtigen Reihenfolge gespeichert (standardmäßig aufsteigende Reihenfolge). .
private transient NavigableMap<E,Object> m; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object();
Die NavigableMap im obigen Quellcode ist eine von SrotedMap geerbte Schnittstelle, und ihre Implementierungsklasse ist TreeMap, sodass die Daten im TreeSet über die TreeMap gespeichert werden Auch hier ist PRESENT ein virtueller Wert ohne praktische Bedeutung.
Das Folgende ist ein Verständnis der grundlegenden Verwendung von HashSet aus der Perspektive des Quellcodes:
•Konstruktor (vier Typen)
1.TreeSet() Leerer Konstruktor, initialisiert eine leere TreeMap, standardmäßig in aufsteigender Reihenfolge angeordnet
2.TreeSet(Comparator super E> ; Komparator) Übergeben Geben Sie einen benutzerdefinierten Komparator ein, der häufig zum Implementieren absteigender Reihenfolge verwendet wird.
3.TreeSet(Collection erweitert E> c) Übergeben Sie eine Teilmenge c, die zum Initialisieren des TreeMap-Objekts verwendet wird. Die Standardeinstellung ist aufsteigend order
4.TreeSet(SortedSet
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); }
Anwendungsbeispiel
//自定义一个比较器,实现降序排列 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
• Elemente einfügen
1.add(E e) Fügt das angegebene Element ein (implementiert durch Aufruf der put-Methode von TreeMap)
2.addAll(Collection erweitert E> c) Einfügen einer Teilmenge c
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
• Element finden
1.contains(Object o) Bestimmen ob das angegebene Objekt in der Sammlung enthalten ist (implementiert durch Aufruf der Methode „containsKey“ von TreeMap)
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的存储结构及基本用法介绍完毕。
Das obige ist der detaillierte Inhalt vonDetaillierte Analyse des Quellcodes der Set in Java-Sammlungsklasse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!