Java Collections Framework Overview (three) - HashSet de-duplication principle (HashCode)

set Interface

Definition:
 does not contain duplicate set of elements. More formally, the set not including a pair of elements e1 and e2, such e1.equals (e2), and at most an empty element. As this interface to simulate a set of abstract mathematics its name implies.

  • set interface features: disordered, no subscript elements can not duplicate
    set of the interface methods inherited from the Collection of all, detailed reference Collection Interface

HashSet

Definition:
 This class implements the Set interface, backed by a hash table (actually a HashMap instance). Iterative sequence set does not make any guarantee; in particular, it can not guarantee the order remained unchanged for some time. This class allows null elements.

HashSet implementation elements of the principle of non-repetition

1. What is duplicate data?

public class SetCollection {
    public static void main(String[] args){
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("A");
        hashSet.add("B");
        hashSet.add("C");
        hashSet.add("D");
        hashSet.add("E");
        hashSet.add("A");

        for(String s :hashSet){
            System.out.println(s);
        }
    }
}

Obviously, the above procedure for the print result
Here Insert Picture Description
 that the program for the compiler, it Ais clear that having repetitive object, and therefore the output of a run Ainstead of two A, then for A is, whether the second object is repeated delete it? The first object is to cover it? We can use add()the method to test the return value.

method description
boolean add(E e) Adds the specified element to this collection (if not already present).

Modify the code as follows:

public class SetCollection {
    public static void main(String[] args){
        HashSet<String> hashSet = new HashSet<>();
        System.out.println(hashSet.add("A"));
        hashSet.add("B");
        hashSet.add("C");
        hashSet.add("D");
        hashSet.add("E");
        System.out.println(hashSet.add("A"));
        for(String s :hashSet){
            System.out.println(s);
        }
    }
}

Print results are as follows:
Here Insert Picture Description

  • Conclusion:
     The first insert Aelement is successful, when this is inserted into the second A, the program editor being given, because it recognizes that this is a duplicate object, inserted into the collection refused.

2.HashSet how to identify duplicate data?

Or in code as an example:

public class TestHashSet {
    public static void main(String[] args){

        Student s1 =new Student("tom",20,"男",99D);
        Student s2 =new Student("jack",21,"男",97D);
        Student s3 =new Student("marry",20,"女",99D);
        Student s4 =new Student("annie",21,"女",100D);
        Student s5 =new Student("annie",21,"女",100D);

        HashSet<Student> students = new HashSet<>();
        students.add(s1);
        students.add(s2);
        students.add(s3);
        students.add(s4);
        System.out.println(students.add(s1));//插入重复对象(地址重复),不允许插入
        System.out.println(students.add(s5));//插入重复对象(地址不同,内容相同),允许插入
        for (Student student : students){
            System.out.println(student);
        }
    }
}
class Student{
    String name;
    Integer age;
    String gender;
    Double score;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", score=" + score +
                '}';
    }

    public Student(String name, Integer age, String gender, Double score) {
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.score = score;
    }
}

 Carefully read the code, you will find that, when inserted into the Students collection of data, we insert two special data, the address is a duplicate data, but the contents of a different address duplicate data, the results you may have guessed, running code show as below:

Here Insert Picture Description
 Obviously, for us, although s5of a different address and other objects, but the content is and s4completely repeated, then, how to make the program the compiler to identify it? This requires covering the Student class equalsmethod, each attribute value to compare objects the similarities and differences, if the equals()return trueis duplicate data, not vice versa;

//Object.java中的eauals()方法
 public boolean equals(Object obj) {
        return (this == obj);
    }

(IDE user can directly generate the Student class direct equal()method)

code show as below:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) &&
                Objects.equals(age, student.age) &&
                Objects.equals(gender, student.gender) &&
                Objects.equals(score, student.score);
    }

Print result:
Here Insert Picture Description
 Hey ~ ~ ~ and expected not the same, we rewrite equals()method does not really cover package equals(), did not work! Why is this so?
 In fact, in order to save memory space, save resources, although this time the user to write a covering eauals()method, but the compiler saw no need for the program to use. It is - "can be used, but not necessary."
The reason is simple, if the call every time equals(), insert five objects will be called many times it?

(Provided the number of comparisons to n)
, when an object is inserted, no comparison (n = 0)
when inserted into two objects 1 needs to compare times (n = 1)
When inserting three objects need to compare two times (n = 2)
when inserting four objects, a relatively 3 (= n-3)
when inserting five objects, a relatively four times (= n-4)

 Just insert five objects but to call 10 times equals(), apparently will not be necessary, greatly reducing the efficiency of the implementation of the program, the program for equals()use is conditional! This condition is HashCode(hash codes);
 because HashCode algorithm based on a plurality of objects may return the same HashCode (of course, if each object is generated HashCode not be the same, it is not necessary to call the equals()method of)
 specific implementation process is as follows :
Here Insert Picture Description
 this also demonstrates why we alone equals();did not achieve the effect of de-emphasis, therefore, in order to meet different address, the content of the same object can be re-checked, we need to look at intervention, the intervention method is to make a different address, the content same (same properties) of the object has the same HashCode;
 therefore, we can customize the HashCode()parent class's method to cover the HashCode()methods, how to define it? Of course, arbitrarily defined clearly unreasonable, HashCode need to combine individual properties of the object do combine, i.e. the whole object HashCode;
 follows (again in the Student class HashCode()methods):

    @Override
    public int hashCode() {
        return Objects.hash(name, age, gender, score);
    }

Print results again:
Here Insert Picture Description

summary:

  • HashSetBased HashCodeto implement elements can not be repeated
  • When deposited elements HashCodeare the same, it will call equals()to confirm, as a result true, refused to deposit;

LinkedHashSet

 Hash table and linked list implementation of the Set interface, with predictable iteration order. This implementation differs from HashSet, it maintains to run a doubly linked list of all entries. This list defines the iteration ordering, which is inserted into the set of elements (insertion sequence) in this order. Note that if a group member is re-inserted into the insertion sequence is not affected. (E reinserted member if and when a group of s s.contains (e) calls s.add (e) is called immediately before returning true.)
 Because it is a linked list structure, and thus different HashSet, can retain a LinkedHashSet insertion order for us.

public class TestLinkedHashSet {
    public static void main(String[] args){
        LinkedHashSet set = new LinkedHashSet();
        set.add("B");
        set.add("D");
        set.add("A");
        set.add("E");
        set.add("C");

        for (Object o : set){
            System.out.println(o);
        }
    }
}

Print result (insert sequence is constant):
Here Insert Picture Description

  • SortedSort

SetFurther provided that the total ordering elements. Elements using their natural order, or generally create an orderly Setprovided when Comparatorsorting. Change the Setiterator will set in increasing order of elements traversed. It provides several additional operations to take advantage of ordering. (This interface is the set of analogues SortedMap).

  • TreeSet

A NavigableSet Based TreeMap. Ordered element using its (natural ordering), or provided by a set Comparator created, depending on the configuration method used.

public class TestTreeSet {
    public static void main(String[] args){
        TreeSet set = new TreeSet();

        set.add("B");
        set.add("A");
        set.add("D");
        set.add("E");
        set.add("C");
        for (Object o : set){
            System.out.println(o);
        }
    }
}

Print Results:
Here Insert Picture Description

Use TreeSet implement liter Descending

 If you need to use TreeSet sort must be allowed to compare object implements Comparablean interface, and override the compareTo()method, the method defined sort criteria (according to what sort), sort (ascending or descending). Here in ascending order, for example:

public class TestTreeSet {
    public static void main(String[] args){
        TreeSet<Student> students = new TreeSet<Student>();
        students.add(new Student("jack",99D));
        students.add(new Student("tom",90D));
        students.add(new Student("jerry",89D));
        students.add(new Student("kitty",95D));
        students.add(new Student("tony",95D));
        students.add(new Student("simon",95D));

        for (Object o : students){
            System.out.println(o);
        }
    }
}
class Student implements Comparable<Student>{
    String name;
    Double score;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }

    public Student(String name, Double score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        //分数低的靠前
        if(this.score>o.score){
            return 1;
        }else if(this.score<o.score){
            return -1;
        //名字按照字典排序
        }else if (this.name.compareTo(o.name) < 0){
            return -1;
        } else if(this.name.compareTo(o.name) >0){
            return 1;
        }
        return 0;
    }
}

Print Results:
Here Insert Picture Description

summary:

  • Unique elements based on achieving the order
  • Implements SortedSet interface automatically order the collection elements
  • Type element objects must implement Comparablethe interface, covering CompareTo()method, designated collation.
Published 82 original articles · won praise 124 · views 110 000 +

Guess you like

Origin blog.csdn.net/qq_44717317/article/details/104704124