java中的Set系列集合:HashSet、LinkedHashSet、TreeSet

1.集合的分类:如下图

2.HashSet集合的概述和特点

● 无序(不代表乱序)

●不可重复(不能存储重复元素),

●没有索引,不能用普通的for进行遍历,但是能用迭代器或者增强for循环进行遍历

● 底层采用数组+链表+红黑树的结构形式来存储数据,其实就是用HashMap的key键来存储数据,在创建HashSet对象的时候就会创建一个HashMap来存储数据(如下图),所以其采用HashMap存储数
 

    public HashSet() {
        map = new HashMap<>();
    }

● 扩容机制:

① 当底层数组长度大于等于阈值的时候(阈值也就是数组长度*负载因子),扩容为原来的2倍。

② 当链表长度大于等于8的时候,并且数组长度小于64。

注意:(如果链表长度大于8,并且数组长度大于等于64该链表会变成红黑树)

3.LinkedHashSet集合

LinkedHashSet是HashSet的子类,其底层用的是LinkedHashMap,LinkedHashSet在HashSet的基础上增加了一个双向链表来维护元素的插入顺序。这意味着元素的迭代顺序与它们被添加到集合中的顺序相同。因此,LinkedHashSet是有序的。

4.TreeSet集合。

●结构:TreeSet是采用红黑树进行存储数据。
●不可重复性:能够和HashSet一样去重

●排序:能够在存放数据的时候对数据排序,相较于HashSet,TreeSet是有序的,能够对对元素按照一定的规则(可以自定义规则)进行排序。

●注意:想要使用TreeSet添加数据,那么添加的那个对象的类需要实现Comparable接口且实现compareTo方法,如果不想实现Comparable接口,

可以在创建TreeSet集合的时候传入该类的比较器(comparator)

演示如下:

 ①类实现Comparable接口并且重写compareTo方法代码演示

 实体类

public class Teacher implements Comparable<Teacher>{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

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

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

    public int getAge() {
        return age;
    }

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

    public Teacher() {
    }

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

    @Override
    public int compareTo(Teacher o) {
        //年龄相同按照名字进行排序
        if (this.age==o.age){
            return this.name.compareTo(o.name);
        }
        //年龄不同按照年龄进行升序排序
        return this.age-o.age;
    }
}

测试类

import java.util.*;

public class test {
    public static void main(String[] args) {
        TreeSet<Teacher> set = new TreeSet<>();
        Teacher teacher1 = new Teacher("b", 2);
        Teacher teacher2 = new Teacher("a", 1);
        Teacher teacher3 = new Teacher("b", 1);
        set.add(teacher1);
        set.add(teacher2);
        set.add(teacher3);
        for (Teacher teacher:set){
            System.out.println(teacher.toString());
        }
    }
}

 测试结果:

②在创建TreeSet集合的时候传入该类比较器作为参数实现TreeSet排序功能  代码演示

实体类

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

    public String getName() {
        return name;
    }

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

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

    public int getAge() {
        return age;
    }

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

    public Teacher() {
    }

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

}

测试类


import java.util.*;

public class test {
    public static void main(String[] args) {
        //Teacher类的比较器,与Teacher类实现Comparable接口并重写compareTo方法效果一致
        Comparator<Teacher> comparator = new Comparator<Teacher>() {
            @Override
            public int compare(Teacher o1, Teacher o2) {
                if (o1.getAge()==o2.getAge()){
                    return o1.getName().compareTo(o2.getName());
                }
                return o1.getAge()-o2.getAge();
            }
        };
        TreeSet<Teacher> set = new TreeSet<>(comparator);
        Teacher teacher1 = new Teacher("b", 2);
        Teacher teacher2 = new Teacher("a", 1);
        Teacher teacher3 = new Teacher("b", 1);
        set.add(teacher1);
        set.add(teacher2);
        set.add(teacher3);
        for (Teacher teacher:set){
            System.out.println(teacher.toString());
        }
    }
}

测试结果

 注意:实现Comparable接口重写的compareTo方法和比较器重写的compare方法的返回值代表什么?

            返回值为0 新的元素和旧的元素相同 新的元素不进行添加

            返回值为>0 将新的元素方法放在旧的元素右边的子节点上

            返回值为<0 将新的元素方法放在旧的元素左边的子节点上

5.常见面试题

hashCode相等,equals一定相等吗?
答:不一定。在java中,hashcode方法是用来获取对象的哈希码,而equals是用来比较两个对象是否相等。但是在某些特殊情况下,可能会出现不同的对象拥有相同的哈希码,这种情况就被我们称之为hash冲突。所以hashcode相等也会出现equals不相等的情况

②equals相等,hashcode一定相等吗?

答:一定,因为当两个对象用equals作比较之后,如果返回true,那么他们的哈希码也一定会相等。比如HashSet和HashMap集合在添加元素的时候,元素的位置就是考哈希码来决定的,如果两个相等的对象拥有不同的哈希码,那么在集合操作中就会出现问题,比如去重失败等等。

3、既然hashset基于hashmap实现,你说一下 hashset的add方法中,为什么要在map.put的val上放上一个object类型的静态常量PRESENT?
答:hashset的add方法默认的调用的map的put方法,如果put方法添加数据成功,那么put方法就会返回null,添加失败,则会返回对应的PRESENT的值,如果PRESENT的值为null,那么我们则无法判断是否添加数据成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值