PS: I am a piece of cake, so this article is self-study after a summary, prawns please you drift over
Set class overview
Set is the simplest collection, the objects in the collection are not sorted in a particular way, and there are no duplicate objects.
There is no obvious order between multiple objects in the set set, essentially the same as the collection method. Just behave differently (set does not allow repeating elements).
HashSet
HashSet stores the elements of a collection by a hash algorithm, so it has good access and lookup performance.
Characteristics:
HashSet is not synchronous, multiple thread accesses are required to ensure synchronization through code
The collection element value can be null.
Note: The HashSet store custom object must override the Hashcode () and Equals () methods
overriding Hashcode Basic guidance:
1. Initialize an shaping variable that assigns a nonzero constant value to this variable, such as the following: int result = 1;
2. Computes an int hash code c for each meaningful domain F in the object (that is, each field that can do the Equals () operation)
Booleanc= (f?0:1) byte,char,short,intc= (int) flongc= (int) (f^ (f>>>32)) floatc=float.floattointbits (f) Doublec=double.doubletolongbits (f) If the result is a long type, use the above rule to process long to get the Intobjectc=f.hashcode () array to apply the above rule to each element
3. The combined calculation obtains the hash code:
result = * result + C;
4. Return result
5. Check the results of the last generation of hashcode () to ensure the same hash code for the same object
Class Person {private string name;private int age;public person (String name, Int. age) {this.name = Name;this.age = age;} /* Why Choose 31? * 1,31 is a prime, prime number is can be divisible by 1 and itself, reduce the multiplication of the same value of the case * 2,31 This number is neither large nor small * 3,31 This number is good, 2 of five square -1,2 left to move 5 bit */@Overridepublic int hashcode () { final int prime = 31;int result = 1;result = Prime * result + Age;result = Prime * result + (name = = null)? 0:name.has Hcode ()); return result;} @Overridepublic Boolean equals (Object obj) {if (this = = obj)//The object being called and the object passed in is the same object return true;if (obj = = null)//Incoming object is Nullre Turn false;if (getclass () = Obj.getclass ())//Determines whether the byte-code file corresponding to two objects is the same byte code return false; person other = (person) obj;if (age! = other.age)//The following compares the fields of the object return false;if (name = = null) {if (other.name! = null) return F Alse;} else if (!name.equals (other.name)) return False;return true;} @Overridepublic String toString () {return ' person [name= + name + ', age= ' + Age + '] ";}}
Test class:
public static void Main (string[] args) {hashset<person> HashSet = new hashset<> (), Hashset.add (New person ("Zhang San Hashset.add ("Zhang San"), Hashset.add ("New Person" ("John Doe"), "Hashset.add" ("John Doe", 23)); Hashset.add ("Harry"), Hashset.add (New person ("Zhao Liu")), and for (person Person:hashset) {System.out.println ( person);}}
Results
person [name= Zhao Liu, Age=25]person [name= Zhang San, age=23]person [name= John Doe, Age=24]person [name= John Doe, Age=23]person [name= Harry, age=25]
See, the result is not to repeat, but to be disordered.
How does HashSet guarantee the uniqueness of the elements?
public class Hashset<e>extends abstractset<e>implements Set<e>, cloneable, java.io.serializable{ Private transient hashmap<e,object> map;private static final Object PRESENT = new Object ();p ublic HashSet () { ma p = new hashmap<> (); } Public iterator<e> Iterator () { 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); } Public boolean Add (E e) { return Map.put (E, PRESENT) ==null; } public boolean remove (Object o) { return Map.Remove (o) ==present; } public void Clear () { map.clear (); }}
See its source (JDK1.8), its bottom-up depends on the hashmap, because it does not involve hashmap, it is a simple overview of its principles, the following will be introduced in detail
The use of set sets is the need to remove duplicate elements, if at the time of storage by equals () comparison, low efficiency, hashing algorithm to improve the efficiency of de-duplication, reduce the use of the Equals () method of the number of
When storing an object, first call the object's Hashcode () method to get a hash value, and then look in the collection for an object with the same hash value
If no object with the same hash value is deposited directly into the collection
If there is an object with the same hash value, the Equals () comparison is performed on the same object as the hash value, and the result of the comparison is false to deposit, true does not exist
Object of custom class deposit HashSet to repeat
The hashcode () and Equals () methods must be overridden in a class
Hashcode (): The same object return value must be the same as the property, the return value of different properties is as different as possible (improve efficiency)
Equals (): property returns True only if the property is different, returns false, and returns false when the store
Linkedhashset
public class Hashset<e>extends abstractset<e>implements Set<e>, cloneable, java.io.serializable{ HashSet (int initialcapacity, float loadfactor, Boolean dummy) { map = new Linkedhashmap<> (initialcapacity, Loadfactor);} } public class Linkedhashset<e>extends hashset<e>implements Set<e>, cloneable, java.io.Serializable { Public Linkedhashset () { super (+,. 75f, True); }}
See its source (JDK1.8), its bottom-up depends on the Linkedhashmap, but Linkedhashmap is also inherited from HashMap, so in the final analysis he still relies on hashmap
See its name, it is different from the hashset is that he is orderly, so he can guarantee how to save how to take
Maintained a doubly linked list in its linkedhashmap
Transient linkedhashmap.entry<k,v> head;transient linkedhashmap.entry<k,v> tail;static class Entry<K, V> extends hashmap.node<k,v> { entry<k,v> before, after; Entry (int hash, K key, V value, node<k,v> next) { super (hash, key, value, next);} } node<k,v> newNode (int hash, K key, V value, node<k,v> e) { linkedhashmap.entry<k,v> p = New Link Edhashmap.entry<k,v> (hash, key, value, e); Linknodelast (p); return p;} private void Linknodelast (Linkedhashmap.entry<k,v> p) { linkedhashmap.entry<k,v> last = tail; tail = p; if (last = = null) head = p; else { P.before = last; Last.after = P; }}
Simple to use
public static void Main (string[] args) {linkedhashset<person> Set = new linkedhashset<> (); Set.add (New person ("Zhang San", 23)); Set.add (New person ("Zhang San", 23)); Set.add (New person ("John Doe", 24)); Set.add (New person ("John Doe", 23)); Set.add (New person ("Harry", 25)); Set.add (New Person ("Zhao Liu")) and for (person Person:set) {System.out.println (person);}}
Results
person [name= Zhang San, age=23]person [name= John Doe, Age=24]person [name= John Doe, Age=23]person [name= Harry, Age=25]person [Name= 赵六, age=25]
Compared with the results of the above hashset, the order of deposit is the same as the order taken out.
TreeSet
TreeSet is the only implementation of the SortedSet interface, and TreeSet ensures that the collection elements are in a sorted state (elements are ordered).
The TreeSet provides several additional methods:
Comparator comparttor (): Returns the Compara input used by the current set, or returns NULL, indicating a natural sort. Object First (): Returns the element in the collection. Object Last (): Returns the final element in the collection. objiect Lower (Object e): Returns the element that precedes the specified element in the collection (that is, the largest element that is less than the specified element, and the reference element may not be a treeset element). object Higher (object E): Returns the element in the collection after the specified element (that is, the smallest element greater than the specified element, and the reference element may not require an treeset element). SortedSet subset (fromelement, toelement): Returns a subset of this set, ranging from fromelement (contains greater than equals) to toelement (not less than). SortedSet HeadSet (toelement): Returns a subset of this set, consisting of elements less than toelement. SortedSet Tailset (fromelement): Returns a subset of this set consisting of elements greater than or equal to fromelement.
To simply use the following:
public static void Main (string[] args) {treeset<string> TreeSet = new treeset<> (); Treeset.add ("EFG"); Treeset.add ("abc"), Treeset.add ("Abd"), Treeset.add ("abc"), Treeset.add ("BCD"), Treeset.add ("CDE"); System.out.println (TreeSet);} Output:[abc, Abd, BCD, CDE, EFG]
Look at the results of both the de-duplication and the natural sort
What happens when I use a custom class?
public static void Main (string[] args) {treeset<person> TreeSet = new treeset<> (), Treeset.add (New person ("Zhang San Treeset.add ("Zhang San"), Treeset.add ("New Person" ("John Doe", 23)); Exception in thread "main" Java.lang.ClassCastException:Person cannot is cast to java.lang.Comparable
Unfortunately, the error, person this class can not be converted to comparable
Let's look at the declaration of the string class:
Public final class Stringextends objectimplements Serializable, Comparable<string>, charsequence
We see the string, which implements the comparable interface, and the API is available, this interface forces the overall ordering of objects that implement each of its classes, which means that our person class must implement its comparable interface?
The answer is, of course, not necessarily, view TreeSet's API
Public TreeSet (COMPARATOR<? Super E> Comparator)
Within its construction method, a comparator can be passed in: Comparator
People may confuse comparator and comparable, first look at the implementation of the code (sort by age, sort from big to small, age the same as compare names natural sort)
First come to comparator and pass in our comparator inside the constructor.
public static void Main (string[] args) {treeset<person> TreeSet = new treeset<> (New comparator<person> () {@Override//anonymous inner class, within which it is implemented how to compare public int compare (person per1, person per2) {int num = per2.getage ()-per1.getage (); Retu RN num = = 0? Per1.getname (). CompareTo (Per2.getname ()): num;}}); Treeset.add ("Zhang San"), Treeset.add (New person ("Zhang San", ")", Treeset.add ("John Doe"); Treeset.add ( New person ("John Doe"), Treeset.add ("Harry"), Treeset.add (New person ("Zhao Liu")), and for (person Person:treeset) { SYSTEM.OUT.PRINTLN (person);}}
Results
person [name= Harry, Age=25]person [Name= Zhao Liu, Age=25]person [name= John Doe, Age=24]person [name= Zhang San, age=23]person [name= John Doe, age=23]
You may have questions about the sort of Chinese characters, you can replace them with English strings, or look at the code below, and you'll know how to compare
System.out.println ("King:" + (' King ' +0)),//char character corresponding to the Unicode code table value System.out.println ("Zhao:" + (' Zhao ' +0));//Wang: 29579//Zhao: 36213
Then look at the comparable implementation:
To transform our person
Class Person implements comparable<person> {private String name;private int age;public person (String name, Int. age) {this.name = Name;this.age = age;} Public String GetName () {return name;} public int getage () {return age;} @Overridepublic String toString () {return "person [name=" + name + ", age=" + Age + "]";} @Overridepublic int CompareTo (person per) {///This part of the code is the same as the contents of the Comparator.compare method int num = Per.getage ()-this.getage (); return num = = 0? GetName (). CompareTo (Per.getname ()): num;}}
Test:
public static void Main (string[] args) {treeset<person> TreeSet = new treeset<> (), Treeset.add (New person ("Zhang San Treeset.add ("Zhang San"), Treeset.add ("New Person" ("John Doe"), "Treeset.add" ("John Doe", 23)); Treeset.add ("Harry"), Treeset.add (New person ("Zhao Liu")), and for (person Person:treeset) {System.out.println ( person);}}
As you can imagine, this result is the same as the result of the above code. The popular point way to say comparable is to write the comparison code in its own interior, and comparator need to define a class separately to compare it.
Comparable & Comparator
Comparator is located under Package Java.util, while comparable is under package Java.lang
are used to implement the comparison and sorting of elements in the collection, except that comparable is the sort of method implementation defined within the collection, Comparator is the sort implemented outside the collection, so if you want to implement sorting, you need to define it outside the collection Comparator The method of the interface or the method that implements the comparable interface within the collection.
Both methods have advantages and disadvantages, with comparable simple, as long as the implementation of the comparable interface object directly becomes a comparable object, but need to modify the source code, with the advantage of comparator is not to modify the source code, but also to implement a comparator, When a custom object needs to be compared, the comparator and the object are passed together in the past can be compared to size, and in the comparator user can implement their own complex can be common logic, so that it can match some relatively simple objects, so that can save a lot of duplication of work.
A summary of the two comparisons
A. Natural order (comparable)
The Add () method of the TreeSet class promotes the stored object to the comparable type
The CompareTo () method of the calling object and the object comparison in the collection
Stored according to the results returned by the CompareTo () method
B. Comparator order (Comparator)
Create a treeset when you can make a comparator
If a subclass object of comparator is passed in, the TreeSet is sorted in the order of the comparator
The Add () method internally calls the Compare () method in the comparator interface to sort
The object being called is the first parameter of the Compare method, and the object in the collection is the second parameter of the Compare method
The difference between the two ways
TreeSet constructors do not pass anything, by default in the order of comparable in the class (no error ClassCastException)
TreeSet if the comparator is passed in, priority is given to comparator
The bottom of the TreeSet relies on the TreeMap, which maintains a binary sort tree inside, which is then explained in detail
public class Treeset<e> extends Abstractset<e>implements navigableset<e>, cloneable, java.io.serializable{ Private transient navigablemap<e,object> M;//treemap implemented interface private static final Object PRESENT = new Object ();p ublic TreeSet () {This (new treemap<e,object> ()); } Public TreeSet (COMPARATOR<, Super e> Comparator) {This (new treemap<> (Comparator)); } public int size () { return m.size (); } public Boolean isEmpty () { return m.isempty (); } Public Boolean contains (Object o) { return M.containskey (o); } Public boolean Add (E e) { return M.put (E, PRESENT) ==null; } public boolean remove (Object o) { return M.remove (o) ==present; } public void Clear () { m.clear (); }}
Summarize the list and set iterations
List
A. Normal for loop, using get ()
B. Call the iterator () method to get iterator, using the Hasnext () and Next () methods
C. Enhance for loop, as long as the class that can use iterator can be used
The D.vector collection can use the enumeration hasmoreelements () and Nextelement () methods
Set
A. Call the iterator () method to get iterator, using the Hasnext () and Next () methods
B. Enhance the For loop, as long as the class that can use iterator can be used
Java Foundation-set of the collection framework