Original URL: http://www.cnblogs.com/skywang12345/p/3311252.html
Overview
In this chapter, we study the hashset.
We first have a general understanding of HashSet, and then learn its source code, and finally through the example to learn to use HashSet. The content includes:
Part 1th introduction of HashSet
Part 2nd HASHSET data structure
Part 3rd HashSet Source parsing (based on jdk1.6.0_45)
Part 4th hashset Traversal mode
Part 5th HashSet Example
Reprint Please specify source: http://www.cnblogs.com/skywang12345/p/3311252.html
Part 1th introduction of HashSet
HashSet Introduction
HashSet is a collection of elements that do not have duplicates .
It is implemented by HashMap, does not guarantee the order of elements , and HashSet allows the use of NULL elements .
The hashset is not synchronized . If multiple threads access a hash set at the same time, and at least one of the threads modifies the set, it must remain externally synchronized. This is usually done by performing a synchronous operation on the object that naturally encapsulates the set. If such an object does not exist, you should use the Collections.synchronizedset method to "wrap" the set. It is a good idea to do this at creation time to prevent accidental, out-of-sync access to the set:
Set s = collections.synchronizedset (new HashSet (...));
HashSet the iterator returned by iterator () is fail-fast.
The HashSet constructor
HashSet's main API
Boolean Add (E object) void Clear () object Clone () Boolean contains (Object object) Boolean IsEmpty () iterator<e> Iterator () Boolean Remove (Object object) int size ()
part 2nd HASHSET data Structure
The inheritance of HashSet is as follows:
Java.lang.Object ? Java.util.abstractcollection<e> ? Java.util.abstractset<e> ? Java.util.hashset<e>public class hashset<e> extends abstractset<e> implements Set<e Cloneable, java.io.Serializable {}
HashSet and map relationships such as:
Can be seen:
HashSet inherits from Abstractset and implements the set interface.
The essence of HashSet is a collection of "No duplicate elements", which is implemented through HashMap. The hashset contains a "member variable of type HashMap" Map,hashset operation function, which is actually implemented by map.
Part 3rd HashSet source parsing (based on jdk1.6.0_45)
In order to better understand the principle of hashset, the following HashSet source code to make an analysis.
Package java.util;
public class Hashset<e>
Extends abstractset<e>
Implements Set<e>, Cloneable, java.io.Serializable
{
Static final Long serialversionuid = -5024744406713321676l;
HashSet is the content that is saved through the map (HashMap object)
private transient hashmap<e,object> map;
Present is the value that is inserted into the map key-value corresponding to the
Because hashset only need to use key, and HashMap is key-value key value pair;
Therefore, when you add a key-value pair to a map, the value of the key-value pair is fixed present
Private static Final Object PRESENT = new Object ();
Default constructor
Public HashSet () {
Call HashMap's default constructor to create a map
Map = new hashmap<e,object> ();
}
Constructors with a collection
Public HashSet (collection<? extends e> c) {
Create a map.
Why call Math.max (int) (C.size ()/.75f) + 1, 16) and choose a larger tree from (c.size ()/.75f) + 1 and 16?
First, the description (C.size ()/.75f) + 1
Since the efficiency of HashMap (time cost and space cost) is considered, the loading factor of HashMap is 0.75.
When HashMap threshold (threshold =hashmap total size * load factor) < "HashMap Actual Size",
It is necessary to double the capacity of the HashMap.
So, (C.size ()/.75f) + 1 calculates exactly the total space size.
Next, explain why it is 16.
The total size of the hashmap must be 2 times the number of points. If the HashMap is created, the specified size is not 2 times the number of points;
The HashMap constructor also recalculates to find the number of exponential multiples of the smallest 2 larger than the "specified size".
So, the designation here for 16 is from performance considerations. Avoid repeating calculations.
Map = new Hashmap<e,object> (Math.max ((int) (C.size ()/.75f) + 1, 16));
Add all elements from the collection (c) to the HashSet
AddAll (c);
}
Constructors that specify hashset initial capacity and load factor
Public HashSet (int initialcapacity, float loadfactor) {
Map = new Hashmap<e,object> (initialcapacity, loadfactor);
}
constructor that specifies the initial capacity of the HashSet
Public HashSet (int initialcapacity) {
Map = new hashmap<e,object> (initialcapacity);
}
HashSet (int initialcapacity, float loadfactor, Boolean dummy) {
Map = new Linkedhashmap<e,object> (initialcapacity, loadfactor);
}
Returns an iterator to the HashSet
Public iterator<e> Iterator () {
Actually returns an iterator to the HashMap "key Collection"
Return Map.keyset (). iterator ();
}
public int size () {
return Map.size ();
}
public Boolean isEmpty () {
return Map.isempty ();
}
Public Boolean contains (Object o) {
return Map.containskey (o);
}
add Element (e) to HashSet
Public boolean Add (E e) {
Return Map.put (E, PRESENT) ==null;
}
Delete an element in HashSet (o)
public boolean remove (Object o) {
return Map.Remove (o) ==present;
}
public void Clear () {
Map.clear ();
}
Clones a hashset and returns the object objects
Public Object Clone () {
try {
hashset<e> Newset = (hashset<e>) super.clone ();
Newset.map = (hashmap<e, object>) Map.clone ();
return newset;
} catch (Clonenotsupportedexception e) {
throw new Internalerror ();
}
}
Write function for java.io.Serializable
Writes HashSet's "total capacity, load factor, actual capacity, all elements" to the output stream
private void WriteObject (Java.io.ObjectOutputStream s)
Throws Java.io.IOException {
Write out any hidden serialization magic
S.defaultwriteobject ();
Write out HASHMAP capacity and load factor
S.writeint (Map.capacity ());
S.writefloat (Map.loadfactor ());
Write out Size
S.writeint (Map.size ());
Write elements in the proper order.
For (Iterator I=map.keyset (). Iterator (); I.hasnext ();)
S.writeobject (I.next ());
}
Read function of java.io.Serializable
The HashSet "Total capacity, loading factor, actual capacity, all elements" is read in turn
private void ReadObject (Java.io.ObjectInputStream s)
Throws Java.io.IOException, ClassNotFoundException {
Read in any hidden serialization magic
S.defaultreadobject ();
Read in HASHMAP capacity and load factor and create backing HashMap
int capacity = S.readint ();
float loadfactor = S.readfloat ();
Map = (((HashSet) this) instanceof Linkedhashset?
New linkedhashmap<e,object> (capacity, loadfactor):
New hashmap<e,object> (capacity, loadfactor));
Read in size
int size = S.readint ();
Read in all elements in the proper order.
for (int i=0; i<size; i++) {
E e = (e) s.readobject ();
Map.put (E, PRESENT);
}
}
}
1 package java.util; 2 3 public class Hashset<e> 4 extends abstractset<e> 5 implements Set<e>, Cloneable, java.io . Serializable 6 {7 static final long serialversionuid = -5024744406713321676l; 8 9//HashSet is a transient hashmap<e,object> map that stores content via map (HashMap object); One//present is to insert the key-value corresponding to the value 13//in the map because the hashset only need to use key, and HashMap is the Key-value key value pair; 14//So, add a key-value pair to the map , the value of the key-value pair is fixed PRESENT the static final object PRESENT = new Object (); 16 17//default constructor public HashSet () {19//Call HashMap's default constructor to create map map = new Hashmap<e,obje Ct> (); 21} 22 23//constructor with set HashSet (collection<? extends e> c) {25//create map. 26//Why call Math.max ((int) (C.size ()/.75f) + 1, 16), choose a larger tree from (c.size ()/.75f) + 1 and 16? 27///First, description (C.size ()/.75f) + 1 28//Because the load factor for HashMap is 0.75, since hashmap efficiency (time cost and space cost) is considered. 29//When hasHmap "threshold" (threshold =hashmap Total size * load factor) < "HashMap Actual size", 30//will need to double the capacity of HashMap. 31//So, (C.size ()/.75f) + 1 calculates exactly the total space size. 32//Next, explain why 16. The total size of the hashmap must be 2 times the number of points. If the HashMap is created, the specified size is not the number of 2, and the constructor of the//HashMap is recalculated to find the number of exponential multiples of the smallest 2 larger than the "specified size". 35//So, the designation here for 16 is from performance considerations. Avoid repeating calculations. Map = new Hashmap<e,object> (Math.max ((int) (C.size ()/.75f) + 1, 16)); 37//Add all elements from the set (c) to HashSet AddAll (c); 39} 40 41//Specify HashSet initial capacity and load factor constructor HashSet (int initialcapacity, float loadfactor) {m AP = new Hashmap<e,object> (initialcapacity, loadfactor); 44} 45 46//Specify the constructor for HashSet initial capacity HashSet (int initialcapacity) {map = new Hashmap<e,o Bject> (initialcapacity); HashSet (int initialcapacity, float loadfactor, Boolean dummy) {map = new linkedhashmap< E,object> (initialcapacity, loadfactor); 53} 54 55 The iterator that returns hashset the public iterator<e> Iterator () {57//actually returns an iterator to the "key collection" of HashMap. Map.keyset (). iterator (); () {66) public int size () {map.size return (); " return Map.isempty (); "Contains" (Object o) {map.containskey return (o); 71} 72 73//Element (E ) Added to HashSet public boolean add (E e) {map.put (E, PRESENT) ==null; 76} 77 78//Delete Hashse The element in T (O) is a public boolean remove (Object o) {map.remove (o) ==present; Bayi} voi D Clear () {map.clear (); 85} 86 87//Clone a HashSet and Return object Object (n)-public object Clone () {89 try {hashset<e> newset = (hashset<e>) super.clone (); Newset.map = (HASHMAP&L T E, object>) Map.clone (); Newset return; Clonenotsupp} catch (Ortedexception e) {94 throw new Internalerror (); The write letter of the Number 99//Will HashSet "total capacity, load factor, actual capacity, all elements" are written to the output stream in the 101 private void WriteObject (Java.io.ObjectOutputStream s) Throws Java.io.IOException {102//Write out any hidden serialization magic103 s.defaultwriteobject (); 1 HASHMAP/Write out capacity and load factor106 S.writeint (map.capacity ()); 107 S.writefloa T (Map.loadfactor ()); 108 109//write out size110 S.writeint (Map.size ()); 111-/write out-all E Lements in the proper order.113 for (Iterator I=map.keyset (). Iterator (); I.hasnext ();) S.writeobject (I.next ());}116 117 118//java.io.Serializable read function 119//Will HashSet "total capacity, load due ReadObject (Java.io.ObjectInputStream s) 121 throws Java.io.IOException, the actual capacity, all elements "sequentially read notfoundexception {122//Read in any HiddeN Serialization magic123 S.defaultreadobject () 124//Read in HASHMAP capacity and load factor and CRE ATE backing HashMap126 int capacity = S.readint () 127 Float loadfactor = S.readfloat (); ((HashSet) this) instanceof Linkedhashset 129 new linkedhashmap<e,object> (capacity, Loadfactor): 130 New hashmap<e,object> (capacity, loadfactor)); 131//Read in size133 int size = S. ReadInt (); 134 135//Read in all elements on the proper order.136 for (int i=0; i<size; i++) {137 E e = (e) s.readobject (); 138 Map.put (E, PRESENT); 139}140}141}
description : The HashSet code is actually very simple and should be well understood through the comments above. It is achieved through the hashmap, if the understanding of hashset is difficult, it is recommended to learn the following hashmap, after learning HashMap, in learning HashSet is very easy.
Part 4th hashset traversal mode
4.1 Traversing HashSet via iterator
First step: get the HashSet iterator based on iterator ().
Step Two: iterate through the iterators to get the individual elements .
Suppose set is a HashSet object for (Iterator Iterator = Set.iterator (); Iterator.hasnext (); ) { iterator.next ();}
4.2 Traversing HashSet via For-each
The first step is to get an array of HashSet's element collections based on ToArray ().
Step Two: iterate through the array to get the individual elements.
Suppose set is a HashSet object, and the element in set is String type string[] arr = (string[]) Set.toarray (new string[0]); for (string Str:arr) System.out.printf ("For each:%s\n", str);
the HashSet Traversal test program is as follows:
Import Java.util.Random;
Import Java.util.Iterator;
Import Java.util.HashSet;
/*
* @desc Introduction HashSet Traversal method
*
* @author Skywang
*/
public class Hashsetiteratortest {
public static void Main (string[] args) {
New HashSet
HashSet set = new HashSet ();
Adding elements to HashSet
for (int i=0; i<5; i++)
Set.add ("+i");
Traverse HashSet via iterator
Iteratorhashset (set);
Traverse HashSet via For-each
Foreachhashset (set);
}
/*
* Traverse HashSet through iterator. Recommended Way
*/
private static void Iteratorhashset (HashSet set) {
for (Iterator Iterator = Set.iterator ();
Iterator.hasnext (); ) {
System.out.printf ("Iterator:%s\n", Iterator.next ());
}
}
/*
* Traverse HashSet through For-each. Not recommended! This method requires that the set be converted to an array
*/
private static void Foreachhashset (HashSet set) {
String[] arr = (string[]) Set.toarray (new string[0]);
for (String Str:arr)
System.out.printf ("For each:%s\n", str);
}
}
1 Import java.util.Random; 2 Import Java.util.Iterator; 3 Import Java.util.HashSet; 4 5/* 6 * @desc Introduction HashSet Traversal Method 7 * 8 * @author Skywang 9 */10 public class Hashsetiteratortest {one public stat IC void Main (string[] args) {13//new HashSet14 HashSet set = new HashSet (); 15 16//Add element to HashSet (int i=0; i<5; i++) Set.add ("" +i); 19 20//iterator traverse HashSet21 Iteratorh Ashset (set), 22 23//Traverse HashSet24 Foreachhashset (set) via For-each, 25}26 27/*28 * through iterator traversal HashSet. Recommended way */30 private static void Iteratorhashset (HashSet set) {Iterator for (Iterator set.iterator = (); 3 2 Iterator.hasnext (); {System.out.printf ("iterator:%s\n", Iterator.next ()); 34}35}36 37/*38 * via For-ea CH Traversal hashset. Not recommended! This method needs to convert the set first to an array of */40 private static void Foreachhashset (HashSet set) {string[] arr = (string[]) set.tOarray (new string[0]); 44%s\n} for a (String Str:arr) System.out.printf ("For each:}45", str);
Operation result :
Iterator:3iterator:2iterator:1iterator:0iterator:4for each:3for each:2for each:1for each:0for each:4
Part 5th HashSet Example
Let's learn how to use HashSet by example
Import Java.util.Iterator;
Import Java.util.HashSet;
/*
* @desc HashSet use of common APIs.
*
* @author Skywang
*/
public class Hashsettest {
public static void Main (string[] args) {
HashSet Common API
Testhashsetapis ();
}
/*
* HashSet other common APIs except iterator () and add ()
*/
private static void Testhashsetapis () {
New HashSet
HashSet set = new HashSet ();
Add an element to the set
Set.add ("a");
Set.add ("B");
Set.add ("C");
Set.add ("D");
Set.add ("E");
Print the actual size of the HashSet
System.out.printf ("Size:%d\n", set.size ());
Determine if HashSet contains a value
System.out.printf ("HashSet contains a:%s\n", Set.contains ("a"));
System.out.printf ("HashSet contains G:%s\n", Set.contains ("G"));
Delete "E" in HashSet
Set.remove ("E");
Convert set to Array
String[] arr = (string[]) Set.toarray (new string[0]);
for (String Str:arr)
System.out.printf ("For each:%s\n", str);
Create a new hashset that contains B, C, F
HashSet otherset = new HashSet ();
Otherset.add ("B");
Otherset.add ("C");
Otherset.add ("F");
Clone a Removeset, the contents and set are identical
HashSet Removeset = (HashSet) set.clone ();
Delete "Removeset, element belonging to Otherset"
Removeset.removeall (Otherset);
Print Removeset
System.out.printf ("Removeset:%s\n", Removeset);
Clone a Retainset, the contents and set are identical
HashSet Retainset = (HashSet) set.clone ();
Preserve "retainset, elements belonging to Otherset"
Retainset.retainall (Otherset);
Print Retainset
System.out.printf ("Retainset:%s\n", Retainset);
Traverse HashSet
for (Iterator Iterator = Set.iterator ();
Iterator.hasnext (); )
System.out.printf ("Iterator:%s\n", Iterator.next ());
Empty HashSet
Set.clear ();
Whether the output HashSet is empty
System.out.printf ("%s\n", Set.isempty ()? " Set is empty ":" Set is not empty ");
}
}
Operation result :
Size:5hashset contains a:truehashset contains g:falsefor each:dfor each:bfor each:cfor each:aremoveset: [D, a ]retainset: [B, C]iterator:diterator:biterator:citerator:aset is empty
Go Java Collection Series 16 HashSet details (source parsing) and usage examples-good