HashSet of Java Basic Knowledge Points

HashSet is a binary tree collection with unique elements, and HashSet is an implementation class of the Set interface (HashSet implements the Set interface), which has the characteristics of Set.
The characteristics of Set are: non-repeatable, elements are out of order, and there is no method with index (so ordinary for loops cannot be used to traverse, nor can the index be used to obtain or delete element values ​​in the Set collection).

The characteristics of HashSet are: the underlying data structure is a hash table; there is no guarantee for the iteration order of the set, that is to say, there is no guarantee that the elements are stored and retrieved in the same order (that is, the elements are out of order); there is no method with an index (so you cannot use ordinary for loop to traverse, nor to obtain or delete the element value in the HashSet collection through the index); it cannot be repeated.

Next we will learn HashSet from the four characteristics of HashSet and combine the code. (Since HashSet does not have an index method, the fourth feature of HashSet can only use forEach statement and Iterator iterator to realize the traversal of HashSet)

注意:同样的,HashSet与TreeSet均是Set接口的一个实现类,因此HashSet的默认数据类型也是Object类,理论上我们可以通过add()方法来添加任意数据类型,但是如果我们这样子做,当我们进行遍历输出的时候就会遇到麻烦!!!因此我们在使用HashSet的时候,请使用泛型来约束数据类型!!!

Since the hash table is also a very important knowledge point, let's skip it here and talk about the last three features of HashSet first. After that, the author will write a knowledge point blog for the hash table separately.

1. Non-repeatable

HashSet of String type

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<String> hashset=new HashSet<>();
        //使用add()方法来添加数据
        hashset.add("bb");
        hashset.add("aa");
        hashset.add("cc");
        hashset.add("ee");
        hashset.add("aaa");
        hashset.add("bb");
        //打印
        System.out.println(hashset);
    }

Running results (duplicate bb elements are filtered out)
insert image description here


Second, use the forEach statement and Iterator iterator to traverse the output HashSet

The forEach statement traverses the output HashSet

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<String> hashset=new HashSet<>();
        //使用add()方法来添加数据
        hashset.add("bb");
        hashset.add("aa");
        hashset.add("cc");
        hashset.add("ee");
        hashset.add("aaa");
        hashset.add("bb");
        //在此我们使用forEach来遍历HashSet
        //String是hashset的数据类型,我们将hashset的数据存入str(此名字你可以自定义)中并输出
        for(String str:hashset){
    
    
            System.out.println(str);
        }
    }

Running results (duplicate bb elements are filtered out)
insert image description here


The Iterator iterator traverses the output HashSet

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<String> hashset=new HashSet<>();
        //使用add()方法来添加数据
        hashset.add("bb");
        hashset.add("aa");
        hashset.add("cc");
        hashset.add("ee");
        hashset.add("aaa");
        hashset.add("bb");
        //创建迭代器对象,由于hashset的类型是String类型,因此迭代器的数据类型也是String
        Iterator<String> iterator=hashset.iterator();
        //判断该位置是否有值,iterator.hasNext()它会查看我们当前位置是否存在元素,存在元素返回true,不存在元素返回false
        while(iterator.hasNext()){
    
    
            //获取该位置的元素值,iterator.next()它会取得我们目前位置的元素,然后指针后移
            System.out.println(iterator.next());
        }
    }

Running results (duplicate bb elements are filtered out)
insert image description here


3. The order of storing and fetching elements is not guaranteed to be consistent

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<String> hashset=new HashSet<>();
        //使用add()方法来添加数据
        hashset.add("zhangsan");
        hashset.add("wangwu");
        hashset.add("lisi");
        hashset.add("aa");
        hashset.add("aaa");
        hashset.add("aa");
        //打印
        System.out.println(hashset);
    }

Running the results (duplicate aa elements are filtered out), we found that the order of our output is inconsistent with the order of insertion, so HashSet does not guarantee that the order of storing and extracting elements is consistent.
insert image description here


4. Case-HashSet collection stores student objects and traverses

The original Student class

public class Student {
    
    
    private String name;
    private int age;

    public Student() {
    
    }

    public Student(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;
    }

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

HsahSet's main() method

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<Student> hashset=new HashSet<>();
        //使用add()方法来添加数据
        hashset.add(new Student("zhangsan",18));
        hashset.add(new Student("zhangsan",18));
        hashset.add(new Student("lisi",18));
        hashset.add(new Student("wangwu",20));
        hashset.add(new Student("chenliu",20));
        //创建迭代器对象,由于hashset的类型是Student类型,因此迭代器的数据类型也是Student
        Iterator<Student> iterator=hashset.iterator();
        //判断该位置是否有值,iterator.hasNext()它会查看我们当前位置是否存在元素,存在元素返回true,不存在元素返回false
        while(iterator.hasNext()){
    
    
            //获取该位置的元素值,iterator.next()它会取得我们目前位置的元素,然后指针后移
            System.out.println(iterator.next());
        }
    }

In the main() method, we insert two identical objects, and we check whether duplicate values ​​will be screened out.
Running results (we find that both of them are output, and the duplicate values ​​we think are not screened out)
insert image description here


那么这是为什么呢?其实我们在元素进行比较的时候,计算机并不是通过比较他们的对象值来判定他们是否不同,而是通过比较他们存储的内存地址来比较他们是否不同,那么我们接下来分别输出它们的HashCode()的值(对象存储的内存空间的int类型数值)

hashCode's main() method

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<Student> hashset=new HashSet<>();
        //创建Student对象
        Student s1=new Student("zhangsan",18);
        Student s2=new Student("zhangsan",18);
        //打印hashcode值,观察他们的内存地址是否相同
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }

operation result(We found that the hashCode values ​​​​of the two of them are different, which is why the computer does not think they are the same
insert image description here


那么我们如何使得计算机知道他们两个是相同的呢,这就需要我们在Student类中重写HashCode()方法

Improve the Student class
笔者用的编译器是IDEA,在IDEA的Student类中右键--->Generate...
insert image description here


选中equals() and hashCode()
insert image description here


点击Next
insert image description here


点击Next
insert image description here


点击Next
insert image description here


点击Finish
insert image description here


The rewritten Student class

public class Student {
    
    
    private String name;
    private int age;

    public Student() {
    
    }

    public Student(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;
    }

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

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

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

hashCode's main() method

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<Student> hashset=new HashSet<>();
        //创建Student对象
        Student s1=new Student("zhangsan",18);
        Student s2=new Student("zhangsan",18);
        //打印hashcode值,观察他们的内存地址是否相同
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }

The running results are as follows: (we can see that the computer already thinks that s1 and s2 are the same)
insert image description here

Run the following main() method

public static void main(String[] args) {
    
    
        //若要使用HashSet,我们需要导入import java.util.HashSet;
        //我们使用泛型来约束HashSet的数据类型为String数据类型
        HashSet<Student> hashset=new HashSet<>();
        //创建Student对象
        Student s1=new Student("zhangsan",18);
        Student s2=new Student("zhangsan",18);
        //添加对象
        hashset.add(s1);
        hashset.add(s1);
        //1:普通打印
        System.out.println(hashset);

        System.out.println("====华丽的分割线====");

        //2:forEach打印
        for(Student stu:hashset){
    
    
            System.out.println(stu);
        }

        System.out.println("====华丽的分割线====");

        //3:Iterator迭代器打印
        Iterator<Student> iterator=hashset.iterator();
        while(iterator.hasNext()){
    
    
            System.out.println(iterator.next());
        }
    }

The running results are as follows: (We can see that the computer already thinks that s1 and s2 are the same at this time, and filters out duplicate values)
insert image description here

OK! ! ! Finish! ! !

Guess you like

Origin blog.csdn.net/qq_45344586/article/details/129701613