Set集合

public class demo1 {
    public static void main(String[] args) {
        //set集合的特点:
        //Set<String> set = new HashSet<>();//经典代码。无序,不重复,无索引
        Set<String> set = new LinkedHashSet<>();//有序(加入时的顺序),不重复,无索引
        set.add("hello");
        set.add("world");
        set.add("java");
        set.add("hello");
        set.add("elysia");
        set.add("elysia");
        set.add("bronya");
        System.out.println(set);

        //TreeSet集合:排序(升序排序),无重复,无索引
        Set<Double> set1 = new TreeSet<>();
        set1.add(40.0);
        set1.add(10.0);
        set1.add(30.0);
        set1.add(20.0);
        set1.add(10.0);
        System.out.println(set1);
    }
}

HashSet集合的底层原理

  • 哈希值
    一个int类型的随机值,Java中每个对象都有一个哈希值
    java中所有对象都可调用Object类提供的hashCode方法返回对象自己的哈希值
  • 对象哈希值特点:
    同一对象多次调用hashCode()方法返回的哈希值是相同的
    不同对象的哈希值大概率不相等,也可能相等(哈希碰撞)

基于哈希表存储数据的

  • JDK8之前:哈希表=数组+链表
    1、创建一个默认长度16的数组,默认装载因子0.75,数组名table
    2、用对应元素的哈希值对数组长度做运算,计算出对应位置
    3、判断当前位置是否为null,是的话直接存入
    4、若不为null,调用equals方法比较:相等,则不存;不同,则存入

JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树

  • JDK8之后:哈希表=数组+链表+红黑树

LinkedHashSet

有序(加入顺序)、不重复、无索引
仍是基于哈希表实现的
每个元素都额外多了一个双链表机制记录其前后元素的位置

TreeSet

可排序,不重复,无索引
底层基于红黑树实现排序

注意
数值类型Integer,Double默认按数值本身大小进行升序排序
对字符串类型:默认按首字母编号升序排序
对自定义对象:TreeSet默认无法直接排序

自定义排序规则

//1、对象类实现Comparable接口,并重写compareTo方法,制定比较规则
public class People implements Comparable<People>{
    private String name;
    private int age;
    private double salary;

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
    //t2.compareTo(t1)
    //t2==this,t1==o
    //规定:你认为左边>右边,返回正整数;
    // 你认为左边<右边,返回负整数;
    // 你认为左边等于右边,返回0
    //默认就是升序
    @Override
    public int compareTo(People o) {
        //按年龄升序
        return this.getAge()-o.getAge();
    }
}

public class demo2 {
    public static void main(String[] args) {
        //TreeSet集合对自定义对象的排序
        TreeSet<People> ts = new TreeSet<>(new Comparator<People>() {
            @Override
            public int compare(People o1, People o2) {
                //return o2.getAge()-o1.getAge();
                /*if(o1.getSalary()>o2.getSalary()){
                    return 1;
                }
                else if(o1.getSalary()<o2.getSalary()){
                    return -1;
                }
                return 0;*/
                return Double.compare(o1.getSalary(),o2.getSalary());
            }
        });//排序,无索引,无重复

        //简化形式
        //TreeSet<People> ts = new TreeSet<>((o1,o2)->Double.compare(o1.getSalary(),o2.getSalary()));
        ts.add(new People("bronya", 18, 5000));
        ts.add(new People("elysia", 19, 6000));
        ts.add(new People("kiana", 20, 3000));
        ts.add(new People("Mae", 20, 9999));
        System.out.println(ts);
        //结论:TreeSet集合默认不能给自定义对象排序
        //解决:
        //1、对象类实现Comparable接口,并重写compareTo方法,制定比较规则
        //2、public TreeSet(Comparator c)集合自带比较器对象,制定比较规则
    }
}

更多推荐