Java set the interface to explain the principles of the HashSet collection

Set Interface

Collection java.util.set interface inherits from the interface, which is consistent with the Collection interface method,
Not to expand the Collection interface function, but more stringent than the collection interfaces.
set interface element is disordered, and will be credited to certain rules to ensure non-duplication of elements.

It is characterized by brief:

  1. Storage is not repeated elements
  2. No index, no indexed methods can not be used for ordinary loop iterates

Set interface implemented with a plurality of classes, java.util.HashSet its usual subclass

Here are some implementation class HashSet set interface

 

HashSet collection introduced

  1. java.util.HashSet set is an implementation of the interface class, its stored element is not repeatable, and (i.e., inconsistent access sequence) elements are disordered.

  2. Java.util.HashSet achieve the underlying fact is supported by a java.util.HashMap

  3. HashSet is determined based on a hash value of the object storage locations in the set of elements, and therefore has good access and search performance.

  4. The only way to ensure the elements depends on: hashCode and equals method.

The code is simple to understand

import java.util.HashSet;
import java.util.Iterator;

public class DemoHashSet {
    public static void main(String[] args) {
        // 创建set集合(HashSet)
        HashSet<String> hashSet = new HashSet<>();

        // use the add method like HashSet collection additive element 
        hashSet.add ( "A" );
        hashSet.add("B");
        hashSet.add("C");
        hashSet.add("D");
        hashSet.add("A");
        System.out.println ( "elements of the collection:" + hashSet);
        System.out.println("==============================");

        // Use iterates over the set of 
        the Iterator <String> = ITE hashSet.iterator ();
         the while (ite.hasNext ()) {
            System.out.println(ite.next());
        }
        System.out.println ( "==============================" );
         // use enhanced for loop through the collection (not Common use for loop, traversal of HashSet collection) 
        for (S String: hashSet) {
            System.out.println(s);
        }
    }
}
Output:
Collection elements: [A, B, C, D]
==============================
A
B
C
D
==============================
A
B
C
D

Note: Common for loop can iterate HashSet collection, storage order HashSet inconsistent set of elements is not repeated, the element

 

HashSet set of structures for storing data (hash table)

What is a hash table

Hash table (also known as hash), which is the basis of the key value (Key - Value) and direct access to the data structure.

In other words, the hash table is accessed through the key value (Key) mapped to a table in a position record (Value), in order to speed up the search. This mapping function called a hash function (hash function), record storage array is called a hash table.

/**
 * Before JDK1.8, the underlying hash table array using linked list implementation +, i.e. conflict linked lists, hash values ​​of the same list are stored in a linked list.
 * But when more elements in a bucket, that is more equal to the hash value of the element, the low efficiency in order to find the key value.
 * And JDK1.8, the hash table using the memory array of + chain + or array + red-black tree to achieve, when the chain length exceeds a threshold value (8), the list is converted into a red-black tree, which greatly reduces the search time.
 * /

 

What is a linked list

List storage unit is a physically non-contiguous, non-sequential storage structure, the logical order of the data elements is achieved by the link pointer in the linked list order. Chain by a series of nodes (each node element is called a linked list), with the node can be dynamically generated at runtime. Each node consists of two parts: a data field storing data elements, and the other is stored under a node address pointer field.

 

What is the red-black tree

Red-black trees (symmetric binary B-tree also known), is a self-balancing binary search tree is a data structure used in computer science, typical use is to realize an associative array .

 

What is an associative array

Array index is a special way. It can only be indexed by an integer, may also (except NULL) which uses an index to a string, or other types of values.

 

Hash value

Understand what a hash table, the simple understanding of what is a hash value

What hash value

Through some hashing algorithm, the data is mapped to a longer period of small short binary data, this data is small hash value of big data.

 

Feature

He is the only, once the big data has changed, even if it is a minor change, he will change the hash value.

 

effect

The main purpose is for the file checksum or signature.

 

The hash value of the Java program

/ ** 
 * hash value in Java: is a decimal integer, a random binary number given by the system obtained after conversion 
* fact, it is the object of the address values, is a logical address, the address obtained is simulated, and physical address is not the data is actually stored
* * There is a method in the Object class, you can obtain the hash value of the object: * Int hashCode () Returns the hash code value
* the hashCode () method Source:
* Native public int the hashCode ();
* Native: This method is invoked on behalf of the local operating system process
* /
// just create a class 
public  class the Person the extends Object {
     Private String name;
     Private  int Age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
// create an object using this class, see the hash value of the object 
public  class DemoHashCode {
     public  static  void main (String [] args) {
         // create a p1 objects, see its hash value of 
        the Person p1 = new new the Person ( "LeeHua" , 21 );
         // calling the hashCode method of Object to get the hash value, the hash value p1 is constant 
        int h1 = p1.hashCode ();
        System.out.println(h1);

        // create a p2 objects, see its hash value of 
        the Person p2 = new new the Person ( "WanTao", 20 );
         // calling the hashCode method of Object to get the hash value, the hash value of p2 is constant 
        int h2 = p2.hashCode ();
        System.out.println(h2);

        // Check p1, p2 address value 
        System.out.println (p1);
        System.out.println(p2);
    }
}
Output:
 1639705018
1627674070
view.study.demo18.Person@61bbe9ba
view.study.demo18.Person@610455d6

 

If overwritten hashCode method, the hash value of the object created will be affected

Such as:

public class Person1 extends Object{

    /**
     * Override the hashCode method
     * @Return the hash value
      * /
    @Override
    public int hashCode() {
        return 666;
    }
}
public  class DemoHashCode1 {
     public  static  void main (String [] args) {
         // create a p1 object view whose hash value 
        of Person1 p1 = new new of Person1 ();
         // call Object hashCode method of obtaining the hash value, the p1 hash value is a constant 
        int h1 of = p1.hashCode ();
        System.out.println(h1);

        // Check p1, p2 address value 
        System.out.println (p1);
    }
}
Output:
 666 
view.study.demo18.Person1@29a

 

Such as: We used the String class, it also covers override hashCode method

public class DemoStringHashCode {
    public static void main(String[] args) {
        /*
        The hash value of the String class
        (String class overrides hashCode method of the Object class)
         */
        String s1 = new String("LeeHua");
        String s2 = new String("WanTao");
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }
}
Output:
 -2022794392
-1711288770

 

Image understanding

 

Can be seen, each position of the array into a constant value, the value of each section corresponds to a hash value.

When the number of values ​​than 8, when using an array of red-black tree +; when the number of values ​​is less than 8, when using an array list +

Such as:

Hash values ​​are 1, 2, 11

Hash values ​​are 13, 14, 15

Value a, b, c, d, e, f, g is a hash value 89

 

Set a collection of storage elements of the principle of non-repetition

principle

set set when calling add () method, add () method calls element hashCode () and equals () method determines whether to repeat elements

 

Code Example

import java.util.HashSet;

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

        HashSet<String> hashSet = new HashSet<>();

        String s1 = new String("abc");
        String s2 = new String("abc");

        hashSet.add(s1);
        hashSet.add(s2);
        hashSet.add("一号");
        hashSet.add("二号");

        System.out.println("s1的哈希值:" + s1.hashCode());
        System.out.println("s2的哈希值:" + s2.hashCode());
        System.out.println("一号的哈希值:" + "一号".hashCode());
        System.out.println("二号的哈希值:" + "二号".hashCode());
        System.out.println("HashSet集合:" + hashSet);
    }
}
输出结果:
s1的哈希值:96354
s2的哈希值:96354
一号的哈希值:640503
二号的哈希值:644843
HashSet集合:[二号, abc, 一号]

 

代码讲解

最初,hashSet集合是空的

hashSet.add(s1)的时候,

第一步:add()方法首先会调用s1的hashCode()方法,计算字符串"abc"的哈希值,其哈希值是96354

第二步:查找集合中哈希值是96354中的元素,没有发现哈希值是96354的key

第三步:将s1存储到集合hashSet中(于是集合hashSet中存在哈希值96354,且对应这数据s1)

 

hashSet.add(s2)的时候

第一步:add()方法首先会调用s2的hashCode()方法,计算字符串"abc"的哈希值,其哈希值是96354

第二步:查找集合hashSet中是否存在哈希值是96354,即哈希值96354冲突,

第三步:s2调用equals()方法,和集合中哈希值是96354对应的元素进行比较

第四步:s2.equals(s1)返回true,即哈希值是96354对应的元素已经存在,所以就不添加s2进集合了(其中:s1 = "abc",s2 = "abc")

 

hashSet.add("一号")的时候

第一步:调用 "一号" 的hashCode()方法,计算字符串 "一号" 的哈希值,其哈希值是640503

第二步:查找集合中哈希值是640503中的元素,没有发现哈希值是640503的key,

第三步:将 "一号" 存储到集合hashSet中(于是集合hashSet中存在哈希值640503,且对应这数据 "一号")

 

hashSet.add("二号")的时候

第一步:调用 "二号" 的hashCode()方法,计算字符串 "二号" 的哈希值,其哈希值是644843

第二步:查找集合中哈希值是644843中的元素,没有发现哈希值是644843的key,

第三步:将 "二号" 存储到集合hashSet中(于是集合hashSet中存在哈希值644843,且对应这数据 "二号")

添加完成,集合hashSet = [abc, 一号, 二号]

 HashSet存储自定义类型元素

hashSet存储自定义类型元素,那么自定义的类必须重写hashCode()方法和equals()方法,否则添加的元素可以出现重复,我们平时使用的类型,它们都重写类hashCode()方法和equals()方法。

假如不重写hashCode()方法和equals()方法

例子:

// 随便创建一个类,作为HashSet存入数据的类型
public class Person{
    private String name;
    private int age;

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

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 

阿里巴巴Java Code规范会抛出警告

 

 

测试一下会出现什么情况

import java.util.HashSet;

public class Demo01PersonHashSet {
    public static void main(String[] args) {
        HashSet<Person> hashSet = new HashSet<>();

        Person p1 = new Person("小明", 20);
        Person p2 = new Person("小明", 20);
        Person p3 = new Person("小红", 20);

        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);
        System.out.println(hashSet);
    }
}
输出结果:
[Person{name='小明', age=20}, Person{name='小明', age=20}, Person{name='小红', age=20}]

可以看到,hashSet集合里面可以存在重复的元素

 

重写hashCode()方法和equals()方法

还是上面这个例子:

在Person类里面添加要重写hashCode()、equals()方法的代码即可,要添加的代码如下

public class Person{
    @Override
    public boolean equals(Object o) {
        // 参数 == 对象
        if (this == o) {
            return true;
        }
        // 传入参数为空,或者对象与参数的hashCode不相等
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        // 向下转型,把Object类型转型为Person类型
        Person person = (Person) o;
        // 返回 age,name
        return age == person.age &&
                Objects.equals(name, person.name);
    }

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

再次用上面的代码测试一下Person类型的数据添加是否会出现重复

输出结果:
[Person{name='小明', age=20}, Person{name='小红', age=20}]

可以看到,输出结果中,hashSet集合的元素并没有重复,因此,如果我们想要用HashSet集合存储自定义类型的数据,一定要记得覆盖重写hashCode()方法和equals()方法

Guess you like

Origin www.cnblogs.com/liyihua/p/12194084.html