第7章-第4节-Java中的Set集合和自然排序compareble

1、HashSet:

1)、 Set集合的特点

  • 元素存储可以有序,可以无序(要看选择的具体子类 HashSet 无序 LinkedHashSet(有序),TreeSet(排序))

  • 没有索引,不能通过索引获取元素(即也不能使用普通for循环遍历)

  • 不可以存储重复的元素

    在某一些特定的场景,我们想要实现不能保存重复的元素的效果,此时使用Set集合就非常的合适

2)、 概述及特点

概述:HashSet集合是Set集合的子类,是一个具体的类。底层使用Hash表存储数据(hash本质就是一个数组)。HashSet存储数据使用的是HashMap的key部 分(HashMap我们明天会学习到,是一个双列的存储数据的结构)

存储数据的结构:数组 + 链表 + 红黑树

特点

  • 元素存储无序

  • 没有索引,不能通过索引获取元素(即也不能使用普通for循环遍历)

  • 不可以存储重复的元素

3)、 常用方法 

1>、增加:

import java.util.HashSet;
import java.util.Set;

public class AddDemo {
    public static void main(String[] args) {
        Set<Integer> set = new HashSet<>();
        // 添加元素
        set.add(1);
        set.add(2);
        set.add(3);
        set.add(17);
        System.out.println(set);

        Set<String> set2 = new HashSet<>();
        // 添加元素
        set2.add("zhangsan");
        set2.add("lisi");
        set2.add("wangwu");
        set2.add("zhaoliu");
        set2.add(null);// 允许添加null值,但是只能添加一次
        System.out.println(set2);
    }
}

2>、删除:

import java.util.HashSet;
import java.util.Set;

public class RemoveDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        // 添加元素
        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhaoliu");
        System.out.println(set);

        // 删除元素
        boolean flag = set.remove("zhangsan");
        System.out.println(flag);
        System.out.println(set);

        System.out.println("-----优雅的分隔符-----");

        // 删除部分元素
        Set<String> set2 = new HashSet<>();
        set2.add("lisi");
        set2.add("zhaoliu");
        set2.add("zhangsan");

        boolean result = set.removeAll(set2);
        System.out.println(result);
        System.out.println(set);
        
        // 清空集合
        set.removeAll(set);
        System.out.println(set);
        set.clear();
        System.out.println(set);
    }
}

3>、修改:

import java.util.HashSet;
import java.util.Set;

public class UpdateDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        // 添加元素
        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhaoliu");
        System.out.println(set);

        // 没有修改的方法
    }
}

4>、查询:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SelectDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        // 添加元素
        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhaoliu");
        System.out.println(set);

        // 获取集合的长度
        System.out.println(set.size());

        // 查询是否包含某一个指定的值
        boolean flag = set.contains("zhangsan");
        System.out.println(flag);

        // 集合是否为空
        System.out.println(set.isEmpty());

        // 增强for循环
        for(String str : set) {
            System.out.println(str);
        }

        System.out.println("----------------------");

        // 迭代器
        Iterator<String> iterator = set.iterator();
        while(iterator.hasNext()){
            String value = iterator.next();
            System.out.println(value);
        }
    }
}

4)、底层原理图:

备注:它的底层是用HashMap实现的, HashMap也是类似原理,后面章节会更具体的讲解HashMap。

2、TreeSet:

1)、学习了hashSet,无序不可重复。但是,有些时候,某些场景还是需要按照指定要求对数据进行排序。也就是说,要求我们的数据有序(此处 的有序指的不是存入顺序与取出顺序一致,而是按照指定的规则从大到小或者从小到大排序),比如,在录入学生考试成绩的时候 ,我就希望能够按照绩来进行排序。

很显然,这个功能使用HashSet没有办法实现,所以,我们需要学习TreeSet树结构,二叉树

2)、 概述及特点

概述:TreeSet实现了Set接口,存储的元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法。

  • TreeSet():根据其元素的自然排序进行排序

  • TreeSet(Comparator comparator) :根据指定的比较器进行排序

    特点

  • 存储的元素有序

  • 没有带索引的方法,所以不能使用普通for循环遍历

  • 由于是Set集合,所以不包含重复元素的集合

    数据结构:采用的是红黑树的结构(本质上使用的是TreeMap的key部分)

    常用的方法与HashSet一致,这里不在进行演示,主要是讲解其排序的特点

3) 、保存基本数据类型及字符串

 1>、保存基本数据类型

import java.util.Set;
import java.util.TreeSet;

public class TreeSetDemo01 {
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<>();
        set.add(5);
        set.add(4);
        set.add(2);
        set.add(1);
        set.add(3);
        set.add(3);// 不能保存重复的元素
        System.out.println(set);// 保存的元素有序
    }
}

2>、保存字符串类型

import java.util.Set;
import java.util.TreeSet;

public class TreeSetDemo02 {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhaoliu");
        set.add("zhouqi");
        set.add("wangba");
        set.add("zhousan");// 不能存储重复的元素
        System.out.println(set);// 保存的元素有序
    }
}

3>、保存自定义类型

public class Student {
    private String name;
    private Integer age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
import java.util.Set;
import java.util.TreeSet;

public class TreeSetDemo03 {
    public static void main(String[] args) {
        Set<Student> set = new TreeSet<>();
        set.add(new Student("zhangsan", 21));
        set.add(new Student("lisi", 19));
        set.add(new Student("wangwu", 18));
        set.add(new Student("wangba", 23));
        System.out.println(set);// 保存的元素有序
    }
}

异常为:java.lang.ClassCastException: com.woniu.treeset.Student cannot be cast to java.lang.Comparable。

类型转换异常,说是Student 不能 转换为 Comparable。Comparable在我们的代码里面没有涉及到,为什么会出现这个问题呢?Integer,String也是引用类型,我们在使用的时候没有出现这异常呢。

所以,我们来看一下String的源码

 3、自然排序compareble:

comparable : 自然排序。是一个接口,只提供了一个方法:compareTo。就是排序的比较规则。如果使用TreeSet的无参构造方法保存自定义数据类型,那么该类应该实现comparable 接口,重写compareTo方法

public interface Comparable<T> {
    // 返回值为0,表示两个元素相等
    // 返回值为正整数,表示大于
    // 返回值为负整数,表示小于
    public int compareTo(T o);
}

案例演示

需求:存储学生对象并遍历,创建TreeSet集合使用无参构造方法。

要求:按照年龄从小到大排序。

public class Student implements Comparable<Student>{
    private String name;
    private Integer age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    @Override
    public int compareTo(Student stu) {
        // 排序的规则
        // this表示需要添加进来的元素 --->         set.add(new Student("lisi", 19));  表示的是lisi
        // stu表示需要比较的对象,即已经存进集合里面的对象
        //System.out.println(stu.age + "---" + this.age);
        return this.age - stu.age;
    }
}
import java.util.Set;
import java.util.TreeSet;

public class TreeSetDemo03 {
    public static void main(String[] args) {
        Set<Student> set = new TreeSet<>();
        set.add(new Student("zhangsan", 21));
        set.add(new Student("lisi", 19));
        set.add(new Student("wangwu", 18));
        set.add(new Student("wangba", 23));

        set.add(new Student("zhouqi", 21));
        System.out.println(set);// 保存的元素有序
    }
}

本电子书目录:《Java基础的重点知识点全集》

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zwarwolf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值