Java_Set(HashSet && TreeSet)

Set collection overview

Features: disorder, no subscripts, non-repeatable elements.
Methods: All inherited from the methods in Collection.

Insert picture description here

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

/**
 * 测试Set接口的使用
 * 特点:1.无序,没有下标;2.重复(不能出现相同的)
 * 1.添加数据
 * 2.删除数据
 * 3.遍历【重点】
 * 4.判断
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        Set<String> set=new HashSet<String>();
        //1.添加数据
        set.add("tang");
        set.add("he");
        set.add("yu");
        System.out.println("数据个数:"+set.size());
        System.out.println(set);//无序输出
        //2.删除数据
        /*
         * set.remove("tang"); System.out.println(set.toString());
         */
        //3.遍历【重点】
        //3.1 使用增强for
        for (String string : set) {
    
    
            System.out.println(string);
        }
        //3.2 使用迭代器
        Iterator<String> iterator=set.iterator();
        while (iterator.hasNext()) {
    
    
            System.out.println(iterator.next());
        }
        //4.判断
        System.out.println(set.contains("tang"));
        System.out.println(set.isEmpty());
    }
}

HashSet【Key points】

Calculate the storage location of the element based on HashCode.
When the hash codes of the stored elements are the same, equals will be called for confirmation. If the result is true, the latter will be rejected.

Note: HashSet storage process:
Step 1: Calculate the saved location according to hashCode. If the location is empty, save it directly, otherwise execute the second step.
Step 2: Execute the equals method. If the method returns true, it is considered a duplicate and refuses to store, otherwise a linked list is formed.

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

/**
 * HashSet集合的使用
 * 存储结构:哈希表(数组+链表+红黑树)
 * 1.添加元素
 * 2.删除元素
 * 3.遍历
 * 4.判断
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        HashSet<Person> hashSet=new HashSet<>();
        Person p1=new Person("tang",21);
        Person p2=new Person("he", 22);
        Person p3=new Person("yu", 21);
        //1.添加元素
        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);
        //重复,添加失败
        hashSet.add(p3);
        //直接new一个相同属性的对象,依然会被添加,不难理解。
        //假如相同属性便认为是同一个对象,怎么修改?
        hashSet.add(new Person("yu", 21));
        System.out.println(hashSet.toString());
        //2.删除元素
        hashSet.remove(p2);
        //3.遍历
        //3.1 增强for
        for (Person person : hashSet) {
    
    
            System.out.println(person);
        }
        //3.2 迭代器
        Iterator<Person> iterator=hashSet.iterator();
        while (iterator.hasNext()) {
    
    
            System.out.println(iterator.next());
        }
        //4.判断
        System.out.println(hashSet.isEmpty());
        //直接new一个相同属性的对象结果输出是false,不难理解。
        //注:假如相同属性便认为是同一个对象,该怎么做?
        System.out.println(hashSet.contains(new Person("tang", 21)));
    }
}

If the same attribute is considered to be the same object, how to modify it?

@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;
    Person other = (Person) 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;
}

There are probably two reasons why the
number 31 is used in the hashCode method: 31 is a prime number, such a number can minimize hash conflicts during calculation.
Execution efficiency can be improved, because 31*i=(i<<5)-i, 31 multiplied by a number can be converted into a shift operation, which can be faster; but some people on the Internet question these two points.

TreeSet (red and black tree)

Based on the sort order to achieve non-repetition.
The SortedSet interface is implemented, and the collection elements are automatically sorted.
The type of element object must implement the Comparable interface and specify the sorting rules.
Determine whether it is a repeating element through the CompareTo method.

import java.util.TreeSet;

/**
 * 使用TreeSet保存数据
 * 存储结构:红黑树
 * 要求:元素类必须实现Comparable接口,compareTo方法返回0,认为是重复元素
 */
public class Test {
    
    
    public static void main(String[] args) {
    
    
        TreeSet<Person> persons=new TreeSet<Person>();
        Person p1=new Person("tang",21);
        Person p2=new Person("he", 22);
        Person p3=new Person("yu", 21);
        //1.添加元素
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        //注:直接添加会报类型转换错误,需要实现Comparable接口
        System.out.println(persons.toString());
        //2.删除元素
        persons.remove(p1);
        persons.remove(new Person("he", 22));
        System.out.println(persons.toString());
        //3.遍历(略)
        //4.判断
        System.out.println(persons.contains(new Person("yu", 21)));
    }
}

Looking at the source code of the Comparable interface, I found that there is only one compareTo abstract method, which is implemented in humans:

public class Person implements Comparable<Person>{
    
    
    @Override
	//1.先按姓名比
	//2.再按年龄比
	public int compareTo(Person o) {
    
    
		int n1=this.getName().compareTo(o.getName()); // 字符串本身就具有comparaTo方法
		int n2=this.age-o.getAge();
		return n1==0?n2:n1;
	}
}

In addition to implementing the comparison method in the Comparable interface, TreeSet also provides a constructor with a comparator, which uses an anonymous inner class to implement it:

/**
 * TreeSet的使用
 * Comparator:实现定制比较(比较器)
 */
public class Demo5 {
    
    
	public static void main(String[] args) {
    
    
		TreeSet<Person> persons=new TreeSet<Person>(new Comparator<Person>() {
    
    
			@Override
			public int compare(Person o1, Person o2) {
    
    
				// 先按年龄比较
				// 再按姓名比较
				int n1=o1.getAge()-o2.getAge();
				int n2=o1.getName().compareTo(o2.getName());
				return n1==0?n2:n1;
			}			
		});
		Person p1=new Person("tang",21);
		Person p2=new Person("he", 22);
		Person p3=new Person("yu", 21);
		persons.add(p1);
		persons.add(p2);
		persons.add(p3);
		System.out.println(persons.toString());
	}
}

/**
 * 要求:使用TreeSet集合实现字符串按照长度进行排序
 * helloworld tangrui hechengyang wangzixu yuguoming
 * Comparator接口实现定制比较
 */
public class Demo6 {
    
    
	public static void main(String[] args) {
    
    
		TreeSet<String> treeSet=new TreeSet<String>(new Comparator<String>() {
    
    
			@Override
			//先比较字符串长度
			//再比较字符串
			public int compare(String o1, String o2) {
    
    
				int n1=o1.length()-o2.length();
				int n2=o1.compareTo(o2);
				return n1==0?n2:n1;
			}			
		});
		treeSet.add("helloworld");
		treeSet.add("tangrui");
		treeSet.add("hechenyang");
		treeSet.add("yuguoming");
		treeSet.add("wangzixu");
		System.out.println(treeSet.toString());
        //输出[tangrui, wangzixu, yuguoming, hechenyang, helloworld]
	}
}

Guess you like

Origin blog.csdn.net/zs18753479279/article/details/114075417