[Java study notes] Set interface and its implementation class

table of Contents

1. Overview of Set interface

2.HashSet collection

2.1 Overview

2.2 How does HashSet ensure the uniqueness of elements

2.3 HashSet case

3.LinkedHashSet collection

4.TreeSet collection

4.1 TreeSet stores Integer type elements and traverses

4.2 TreeSet stores custom objects and traverses


1. Overview of Set interface

A Collection that does not contain repeated elements.

2.HashSet collection

2.1 Overview

  • The iteration order of the set is not guaranteed
  • In particular, it does not guarantee that the sequence will last forever

2.2 How does HashSet ensure the uniqueness of elements

  • The bottom layer of the HashSet collection depends on the hash table structure
  • The bottom layer of the hash table structure relies on the hashcode() method and equals() method

2.3 HashSet case

2.3.1 HashSet stores strings and traverses

HashSet stores and traverses strings, and the output result element is unique, because the String class rewrites the hashcode() method and equals() method, so the string with the same content can be removed to ensure the uniqueness of the element.

The underlying principle analysis is as follows:

  • First compare whether the hashcode() values ​​are the same
  • If they are the same, continue to use the equals() method
    • Return true, indicating that the element is duplicated, so do not add
    • Return false, indicating that the element is not repeated, just add it to the collection
  • If they are different, add the element directly to the collection
// 创建集合对象
HashSet<String> hs = new HashSet<String>();

// 添加元素
hs.add("Python");
hs.add("Fiddler");
hs.add("Selenium");
hs.add("Fiddler");

// 增强for遍历集合
for (String str : hs) {
	System.out.println(str);
}

operation result:

Selenium
Fiddler
Python

2.3.2 HashSet stores custom objects and traverses

  • Student(name, age)
  • Requirement: If the values ​​of the member variables of the two objects are the same, they are the same element.

The code of Student.java is as follows:

package com.hw.set;

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

	public Student() {
		super();
	}

	public Student(String name, int age) {
		super();
		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;
	}

}

 The test code is as follows:

// 创建集合对象
HashSet<Student> hs = new HashSet<Student>();

// 创建学生对象
Student s1 = new Student("西施", 20);
Student s2 = new Student("貂蝉", 22);
Student s3 = new Student("昭君", 18);
Student s4 = new Student("貂蝉", 22);

// 把学生对象添加到集合中
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);

// 增强for遍历集合
for (Student stu : hs) {
	System.out.println(stu.getName() + "---" + stu.getAge());
}

The results of the operation are as follows:

西施---20
昭君---18
貂蝉---22
貂蝉---22

The case requires that if the values ​​of the member variables of the two objects are the same, they are the same element. Actually, three student objects should be output, but all four student objects are output. The reason is that the Student class does not override the hashcode() method and equals() method. The two methods of the Object class are used by default. At this time, the hash value of the student is different, so all the four student objects will be output. .

Solution: Rewrite the hashcode() method and equals() method in the Student class.

The code of Student.java that rewrites hashcode() and equals() is as follows:

package com.hw.set;

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

	public Student() {
		super();
	}

	public Student(String name, int age) {
		super();
		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 int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}

3.LinkedHashSet collection

  • The underlying data structure of LinkedHashSet consists of a hash table and a linked list
  • The uniqueness of the element represented by the hash table
  • The linked list ensures that the elements are in order (the storage order and the retrieval order are the same)
package com.hw.set;

import java.util.LinkedHashSet;

/**
 * LinkedHashSet存储字符串并遍历
 * 
 * @author HW
 * 
 */
public class LinkedHashSetDemo {
	public static void main(String[] args) {
		// 创建集合对象
		LinkedHashSet<String> lhs = new LinkedHashSet<String>();

		// 添加元素
		lhs.add("Python");
		lhs.add("Fiddler");
		lhs.add("Selenium");

		// 增强for循环遍历集合
		for (String str : lhs) {
			System.out.println(str);
		}
	}
}

The results of the operation are as follows:

Python
Fiddler
Selenium

4.TreeSet collection

TreeSet can sort the elements according to certain rules.

There are two sorting methods. Which method is used depends on the construction method used. When the construction method is empty, the natural order is used for sorting.

  • Natural sorting: Let the class to which the element belongs to implement the natural sorting interface Comparable<T>, let’s first understand the Comparable<T> interface and compareTo() method:
    • public interface Comparable<T>: This interface forces the overall ordering of the objects of each class that implements it. This ordering is called the natural ordering of classes. The compareTo() method of a class is called the natural comparison method of the class.
    • int compareTo(T o): If the object is less than, equal to, or greater than the specified object, it returns a negative integer, zero, or a positive integer, respectively.
  • Comparator sorting: Let the construction method of the collection receive a subclass object Comparator of the comparator interface

The bottom layer of TreeSet is a binary tree structure to ensure the sorting and uniqueness of elements.

4.1 TreeSet stores Integer type elements and traverses

// 创建集合对象
TreeSet<Integer> ts = new TreeSet<Integer>();
		
// 添加元素
ts.add(20);
ts.add(23);
ts.add(15);
ts.add(6);
ts.add(18);
ts.add(23);
		
// 增强for遍历集合
for (Integer i : ts) {
	System.out.println(i);
}

operation result:

6
15
18
20
23

4.2 TreeSet stores custom objects and traverses

  • Student(name, age)
  • Sort by age from youngest to oldest

4.2.1 Use natural sorting 

To use natural sorting to sort student objects, the Student class must implement the Comparable<T> interface and override the compareTo() method. If the Student class does not implement the Comparable<T> interface, the operation result will report an error: Exception in thread "main" java.lang.ClassCastException: com.hxs.day06.Student cannot be cast to java.lang.Comparable, as shown below:

Now implement this interface in the Student class and override the compareTo() method:

package com.hw.treeset;

/**
 * 如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
 * 
 * @author HW
 * 
 */
public class Student implements Comparable<Student> {
	private String name;
	private int age;

	public Student() {
		super();
	}

	public Student(String name, int age) {
		super();
		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;
	}
	
	public int compareTo(Student s) {
		// 主要条件,按照年龄排序
		int num = this.age - s.age;
		// 次要条件,年龄相同的时候,比较姓名是否相同
		// 如果年龄和姓名都相同,才是同一个元素
		int num2 = num == 0 ? this.name.compareTo(s.name) : num;
		return num2;
	}
}

The test code is as follows:

package com.hw.treeset;

import java.util.TreeSet;

import com.hw.set.Student;

/**
 * TreeSet存储自定义对象并遍历
 * 自然排序,按照年龄从小到大排序
 * 
 * @author HW
 * 
 */
public class TreeSetDemo2 {
	public static void main(String[] args) {
		// 创建集合对象
		TreeSet<Student> ts = new TreeSet<Student>();

		// 创建学生对象
		Student s1 = new Student("linqingxia", 27);
		Student s2 = new Student("zhangguorong", 29);
		Student s3 = new Student("wanglihong", 23);
		Student s4 = new Student("linqingxia", 27);
		Student s5 = new Student("liushishi", 22);
		Student s6 = new Student("wuqilong", 40);
		Student s7 = new Student("fengqingy", 22);

		// 把学生对象添加到集合中
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		ts.add(s7);

		// 增强for遍历集合
		for (Student stu : ts) {
			System.out.println(stu.getName() + "---" + stu.getAge());
		}

	}
}

The results of the operation are as follows:

fengqingy---22
liushishi---22
wanglihong---23
linqingxia---27
zhangguorong---29
wuqilong---40

 4.2.2 Comparator sorting

Let the constructor of the collection receive a subclass object Comparator of the comparator interface.

package com.hw.treeset;

import java.util.Comparator;
import java.util.TreeSet;

import com.hw.set.Student;

/**
 * TreeSet存储自定义对象并遍历 
 * 比较器排序
 * 
 * @author HW
 * 
 */
public class TreeSetDemo3 {
	public static void main(String[] args) {
		// 创建集合对象
		// 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
		// 而匿名内部类就可以实现这个东西
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

			public int compare(Student s1, Student s2) {
				int num = s1.getAge() - s2.getAge();
				int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
						: num;
				return num;
			}

		});

		// 创建学生对象
		Student s1 = new Student("linqingxia", 27);
		Student s2 = new Student("zhangguorong", 29);
		Student s3 = new Student("wanglihong", 23);
		Student s4 = new Student("linqingxia", 27);
		Student s5 = new Student("liushishi", 22);
		Student s6 = new Student("wuqilong", 40);
		Student s7 = new Student("fengqingy", 22);

		// 把学生对象添加到集合中
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		ts.add(s7);

		// 增强for遍历集合
		for (Student stu : ts) {
			System.out.println(stu.getName() + "---" + stu.getAge());
		}
	}
}

​​​​​The running results are as follows:

liushishi---22
wanglihong---23
linqingxia---27
zhangguorong---29
wuqilong---40

 

Guess you like

Origin blog.csdn.net/weixin_44679832/article/details/105461598