JAVA容器-Set接口容器详解

JAVA容器系列专题

【JAVA容器概论】
【JAVA容器-List接口容器详解】
【JAVA容器-迭代器Iterator详解】
【JAVA容器-Set接口容器详解】
【JAVA容器-Map接口容器详解】
【JAVA容器演进及应用(含对Disruptor的浅解)】

Set接口容器关系图

在这里插入图片描述

HashSet的使用

底层实现:哈希表(数组+链表)

public class TestHashSet {
    //这是main方法,程序的入口
    public static void main(String[] args) {
        //创建一个HashSet集合:保存Integer类型元素
        HashSet<Integer> hs = new HashSet<>();
        System.out.println(hs.add(19));//返回true
        hs.add(5);
        hs.add(20);
        //返回false,因为集合中已经有19,所以这个19没有放入到集合中
        System.out.println(hs.add(19));
        hs.add(41);
        hs.add(0);
        // 元素无序且唯一
        System.out.println(hs.size());
        System.out.println(hs);
        
        //创建一个HashSet集合:保存String类型元素
        HashSet<String> hs1 = new HashSet<>();
        hs1.add("hello");
        hs1.add("apple");
        hs1.add("banana");
        hs1.add("html");
        hs1.add("apple");
        hs1.add("css");
        // 元素无序且唯一
        System.out.println(hs1.size());
        System.out.println(hs1);

		//创建一个HashSet集合:保存Student对象元素
        HashSet<Student> hs2 = new HashSet<>();
        hs2.add(new Student(19,"lili"));
        hs2.add(new Student(20,"lulu"));
        hs2.add(new Student(18,"feifei"));
        hs2.add(new Student(19,"lili"));
        hs2.add(new Student(10,"nana"));
        // 元素无序,但是唯一
        System.out.println(hs2.size());
        System.out.println(hs2);
    }
}

代码执行结果反思

执行结果发现:

  1. 对于存储顺序来说,HashSet存储无序。
  2. HashSet中存储Integer、String都能实现元素无序且唯一,但是存储自定义对象却不能实现元素唯一。
  3. Integer、String类型存储多次时,只有第一次存储成功,其余都存储失败。

LinkedHashSet的使用

底层实现:哈希表+链表

public class TestSet {
    public static void main(String[] args) {
        System.out.println("--------------testLinkedHashSet-------------");
        testLinkedHashSet();
        System.out.println("--------------testHashSet-------------");
        testHashSet();

    }
    private static void testLinkedHashSet() {
        LinkedHashSet<Integer> hs = new LinkedHashSet<>();
        System.out.println(hs.add(19));//true
        hs.add(25);
        hs.add(20);
        System.out.println(hs.add(19));//false 这个19没有放入到集合中
        hs.add(41);
        hs.add(0);
        System.out.println(hs.size());//唯一,无序
        System.out.println(hs);
    }
    private static void testHashSet() {
        HashSet<Integer> hs = new HashSet<>();
        System.out.println(hs.add(19));//true
        hs.add(25);
        hs.add(20);
        System.out.println(hs.add(19));//false 这个19没有放入到集合中
        hs.add(41);
        hs.add(0);
        System.out.println(hs.size());//唯一,无序
        System.out.println(hs);
    }
}

代码执行结果

在这里插入图片描述

代码执行结果反思

  1. 对于存储顺序来说,LinkedHashSet存储有序,HashSet存储无序。
  2. LinkedHashSet与HashSet相同,存储的元素都是唯一的。

TreeSet的使用

底层实现:二叉树

测试代码

public class Student {
    private int age;
    private String name;
    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;
    }
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
public class TestSet {
    public static void main(String[] args) {
        System.out.println("--------------testTreeSet-------------");
        testTreeSet();
    }

    private static void testTreeSet() {
        TreeSet<Student> s = new TreeSet<>();
        s.add(new Student(14,"wk"));
        s.add(new Student(2,"tk"));
        s.add(new Student(10,"sjc"));
        System.out.println(s.add(new Student(20, "wj")));
        s.add(new Student(33,"xyc"));
        System.out.println(s.add(new Student(20, "wj")));
        s.add(new Student(5,"tzl"));
        System.out.println(s.size());
        System.out.println(s);
    }
}

执行结果

在这里插入图片描述

反思

因为没有在TreeSet存储的自定义对象中重写排序方法,所以抛异常了,所以TreeSet中存储的元素一定要实现排序方法。

代码修改

public class Student implements Comparable<Student>{
    private int age;
    private String name;
    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;
    }
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }


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

    @Override
    public int compareTo(Student o) {
        return this.getAge() - o.getAge();
    }
}

执行结果

在这里插入图片描述

反思

自定义对象实现Comparable接口,并重写compareTo(),执行成功。

比较器实现

原理

比较器实现的原理就是根据业务逻辑返回【=0,<0,>0】三种值,然后根据返回值放入TreeSet的底层二叉树。

内部比较器

Demo

TreeSet中的Student类属于【内部比较器】。

简介

自定义对象实现Comparable接口,并重写compareTo()。

外部比较器

方式一:新建比较器类

Demo
public class MyCompare implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getAge() - o2.getAge();
    }
}
简介

新建一个类,实现Comparator接口,并重写compare()。

方式二:比较器简略写法

Demo
public class TestSet {
    public static void main(String[] args) {
        System.out.println("--------------testTreeSet-------------");
        testTreeSet();

    }

    private static void testTreeSet() {
        TreeSet<Student> s = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o1.getAge() - o2.getAge();
            }
        });

        s.add(new Student(14,"wk"));
        s.add(new Student(2,"tk"));
        s.add(new Student(10,"sjc"));
        System.out.println(s.add(new Student(20, "wj")));
        s.add(new Student(33,"xyc"));
        System.out.println(s.add(new Student(20, "wj")));
        s.add(new Student(5,"tzl"));
        System.out.println(s.size());
        System.out.println(s);
    }
}
简介

在实例化TreeSet时直接new一个Comparator接口并重写compare()。

反思

  1. 内部比较器只能实现一种比较方式,不推荐。
  2. 外部比较器可以按需为一个自定义对象创建多种比较方式,并且写法简单,推荐使用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值