集合(二):Set : HashSet; LinkedHashSet; TreeSet

集合(二)

Set

    概述及特点:元素唯一,即一个不包含重复元素的 collection。更确切地讲,
set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。

一、HashSet

1、概述及特点

    概述及特点:HashSet 底层数据结构是哈希表,线程不安全,效率高,元素无序(存取顺序
不一致),且唯一(元素不可重复),可以是 null。
    哈希表:JDK1.7之前是数组+链表,JDK1.8之后为数组+链表+二叉树

2、HashSet元素唯一性解析及代码优化

在这里插入图片描述

代码优化

import java.util.HashSet;
import java.util.Objects;

public class Blog1 {
    public static void main(String[] args) {
        //HashSet 之所以能够保证元素的唯一性,是靠元素重写 equals()和hashCode()方法来保证的,如果元素不重写该方法,则不能保证元素的唯一性
        //合理重写hashCode()方法,可以减少调用equals()的次数,也称之为减少碰撞
        //原因:只有当两个对象hashCode()的返回值相同时,才会去调用equals()方法,比较成员变量的内容
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("张三",23));
        hashSet.add(new Student("李四",27));
        hashSet.add(new Student("王五",26));
        hashSet.add(new Student("张三",23));
        hashSet.add(new Student("李四",27));
        hashSet.add(new Student("王五",26));
        hashSet.add(new Student("赵六",25));
        hashSet.add(new Student("张三",24));
        hashSet.add(new Student("曾七",23));
        System.out.println(hashSet);
    }
}
class Student{
    String name;
    int age;

    public Student() {
    }

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

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

    static int count=1;//统计变量
    @Override
    public boolean equals(Object o) {
        System.out.println("equals()方法执行了"+(count++)+"次");
        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);
    }
}	
运行结果:
equals()方法执行了1equals()方法执行了2equals()方法执行了3[Student{name='张三', age=23}, Student{name='李四', age=27}, Student{name='王五', age=26}, Student{name='赵六', age=25}, Student{name='张三', age=24}, Student{name='曾七', age=23}]

Process finished with exit code 0

二、LinkedHashSet

    概述及特点:LinkedHashSet 底层数据结构是链表和哈希表,元素有序且唯一,
链表保证了有序,哈希表保证了唯一,线程不安全,效率高

三、TreeSet

1、概述及特点

    概述及特点:TreeSet 底层数据结构是二叉树,元素唯一,且可以对元素进行排序,
              排序:自然排序,比较器排序

二叉树存储数据保证元素唯一性且排序原理图解

在这里插入图片描述

2、自然排序

    自然排序:如果TreeSet()采用的是空参构造,那么采用的就是自然排序,自然排序要求元素必须
实现一个Comparable接口,并实现这个接口中的一个compareTo比较方法,根据此方法的返回值的
正(右边) 、负(左边)  0(两元素相同,不再向集合添加) 来决定元素排列的位置。

演示

import java.util.TreeSet;

public class Blog2 {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<>();
        treeSet.add(new Student("张三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("张三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("赵六",25));
        treeSet.add(new Student("张三",24));
        treeSet.add(new Student("曾七",23));
        //按照年龄从小到大排序
        System.out.println(treeSet);
    }
}
class Student implements Comparable<Student> {
    private String name;
    private int age;

    public Student() {
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

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

    //重写比较方法
    @Override
    public int compareTo(Student o) {
        //先比较年龄大小,如果年龄大小一样,再去比较名字,如果不比较名字,年龄相同的人就存不到集合中去了
        int num=this.age-o.age;
        int num1=num==0?this.name.compareTo(o.name):num;
        return num1;
    }
}
运行结果:
[Student{name='张三', age=23}, Student{name='曾七', age=23}, Student{name='张三', age=24}, Student{name='赵六', age=25}, Student{name='王五', age=26}, Student{name='李四', age=27}]

Process finished with exit code 0

3、比较器排序

比较器排序:采用有参构造,在创建TreeSet对象时,需要传入一个Comparetor 比较器
        //TreeSet(Comparator < ? super E > comparator)
Comparator<T> 比较器:
        int compare (T o1, T o2);//比较用来排序的两个参数。

演示

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

public class Blog3 {
    public static void main(String[] args) {
        //传入比较器方式:1、可以自己创建一个Comparator<T>接口的子类,并实现 compare方法,传入该接口的子类对象
        //              2、使用匿名内部类,传入比较器,并实现compare方法
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int num=o1.getAge()-o2.getAge();
                int num1=num==0?o1.getName().compareTo(o2.getName()):num;
                return num1;
            }
        });
        treeSet.add(new Student("张三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("张三",23));
        treeSet.add(new Student("李四",27));
        treeSet.add(new Student("王五",26));
        treeSet.add(new Student("赵六",25));
        treeSet.add(new Student("张三",24));
        treeSet.add(new Student("曾七",23));
        //按照年龄从小到大排序
        System.out.println(treeSet);
    }
}
class Student{
    private String name;
    private int age;

    public Student() {
    }

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

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
运行结果:
[Student{name='张三', age=23}, Student{name='曾七', age=23}, Student{name='张三', age=24}, Student{name='赵六', age=25}, Student{name='王五', age=26}, Student{name='李四', age=27}]

Process finished with exit code 0

4、例题

//需求:编写一个程序,获取10个1至20的随机数,要求随机数不能重复,且要对其进行排序
/*-----示例-----*/
import java.util.Random;
import java.util.TreeSet;

public class Blog4 {
    public static void main(String[] args) {
        int number=10;
        Random random = new Random();
        TreeSet<Integer> treeSet = new TreeSet<>();
        //Integer类已经实现Comparable接口,默认从小到大排序
        for (int i = 0; i < number; i++) {
            boolean flag=treeSet.add(random.nextInt(20)+1);//生成随机数尝试添加到集合,并获取是否添加成功的结果
            if(!flag){
                i--;//如果未添加成功,让i-1,多生成一个随机数添加尝试添加到集合
            }
        }
        System.out.println(treeSet);
    }
}
运行结果:
[1, 5, 6, 7, 10, 11, 12, 14, 15, 17]

Process finished with exit code 0

四、Collections工具类

A:Collections类概述:	针对集合操作的工具类
B:Collections常用成员方法
	public static <T> void sort(List<T> list):					排序,默认按照自然顺序
	public static <T> int binarySearch(List<?> list,T key):		二分查找
	public static <T> T max(Collection<?> coll):				获取最大值
	public static void reverse(List<?> list):					反转集合元素
	public static void shuffle(List<?> list):					随机打乱元素
发布了55 篇原创文章 · 获赞 23 · 访问量 4354

猜你喜欢

转载自blog.csdn.net/y_Engineer/article/details/96652147