Bootstrap

Java——集合之Set、HashSet、LinkedHashSet、TreeSet

一、Set集合的特点

  • 不包含重复元素
  • 没有带索引的方法,因此不能使用普通for循环遍历
import java.util.HashSet;
import java.util.Set;

public class Demo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<String>();
        set.add("hello");
        set.add("hello");
        for (String s : set) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述

二、HashSet

1、哈希值

哈希值时JDK根据对象的地址或者字符串或者数字算出来的int类型的数值,hashCode()方法可以返回对象的哈希值

  • 同一个对象多次调用hashCode()方法返回的哈希值相同
  • 默认情况下,不同对象的哈希值不同,但是可以通过重写hashCode()方法实现不同对象的哈希值相同
public class Demo2 {
    public static void main(String[] args) {
        Student s1 = new Student("zlx", 18);
        //同一个对象多次调用hashCode()方法返回的哈希值相同
        System.out.println(s1.hashCode());//1435804085
        System.out.println(s1.hashCode());//1435804085

        //默认情况下,不同对象的哈希值不同
        //通过重写hashCode(),可以实现不同对象的哈希值相同
        Student s2 = new Student("zkl", 20);
        System.out.println(s2.hashCode());//1784662007

        System.out.println("hello".hashCode());//99162322
        System.out.println("world".hashCode());//113318802
        System.out.println("java".hashCode());//3254818

        System.out.println("重地".hashCode());//1179395
        System.out.println("通话".hashCode());//1179395
    }
}

2、哈希表

  • JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
  • JDK8之后,在长度比较长的时候,底层实现了优化

3、HashSet集合的特点

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以不包含重复元素的集合

存储字符串并遍历的示例

import java.util.HashSet;

public class Demo3 {
    public static void main(String[] args) {
        HashSet<String> hash = new HashSet<String>();
        hash.add("hello");
        hash.add("world");
        hash.add("java");
        hash.add("world");

        for (String s : hash) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述

三、LinkedHashSet

  • LinkedHashSet由哈希表和链表实现Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
  • 由哈希表保证元素唯一,也就是说没有重复的元素

LinkedHashSet实现字符串的存储和遍历

import java.util.LinkedHashSet;

public class Demo4 {
    public static void main(String[] args) {
        LinkedHashSet<String> lhs = new LinkedHashSet<String>();
        lhs.add("hello");
        lhs.add("world");
        lhs.add("java");
        lhs.add("world");
        for (String s : lhs) {
            System.out.println(s);
        }
    }
}

在这里插入图片描述

四、TreeSet

1、TreeSet集合的特点

  • 元素有序,这里的有序指的是元素按照一定的规则进行排序,具体排序方式取决于构造方法
    TreeSet():根据其元素的自然排序进行排序
    TreeSet(Comparator comparator):根据指定的比较器进行排序
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以不包含重复元素的集合

2、使用TreeSet存储整数并遍历的示例

import java.util.TreeSet;

public class Demo5 {
    public static void main(String[] args) {
        TreeSet<Integer> ts = new TreeSet<Integer>();
        ts.add(10);
        ts.add(20);
        ts.add(15);
        ts.add(3);
        for (Integer i : ts) {
            System.out.println(i);
        }
    }
}

在这里插入图片描述

3、自然排序Comparable

使用自然排序实现学生对象的输出,按照原则:年龄升序,如果年龄相同按照名字升序。

  • Student类需要实现接口Comparable
  • Student类需要重写方法compareTo()
public 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 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 compareTo(Student s) {
        int num = this.age - s.age;
        int num2 = num == 0 ? this.name.compareTo(s.name) : num;
        return num2;
    }
}
import java.util.TreeSet;

public class Demo6 {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>();
        Student s1 = new Student("zlx", 18);
        Student s2 = new Student("lkx", 25);
        Student s3 = new Student("jik", 18);
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);

        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}

在这里插入图片描述

4、比较器排序Comparator

使用比较器排序实现学生对象的输出,按照原则:年龄升序,如果年龄相同按照名字升序。

  • 在创建TreeSet集合时使用带参构造方法,重写compare()方法
  • Student类中不需要重写compareTo()方法
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;
    }
}
import java.util.Comparator;
import java.util.TreeSet;

public class Demo {
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAge() - s2.getAge();
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
                return num2;
            }
        });
        Student s1 = new Student("zlx", 18);
        Student s2 = new Student("lkx", 25);
        Student s3 = new Student("jik", 18);
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        for (Student s : ts) {
            System.out.println(s.getName() + "," + s.getAge());
        }
    }
}
;