JavaSE学习笔记(五)集合_Collection_Set

1 Set集合

Set集合特点

  • 无序:存取顺序不一致
  • 不重复:可以去除重复
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

Set集合实现类特点

  • HashSet :无序、不重复、无索引。
  • LinkedHashSet有序、不重复、无索引。
  • TreeSet排序、不重复、无索引。

Set集合的功能上基本上与Collection的API一致

2 HashSet

  • HashSet集合底层采取哈希表存储的数据

哈希表是一种对于增删改查数据性能都较好的结构
哈希表的组成

  • JDK8之前的,底层使用数组+链表组成
  • JDK8开始后,底层采用数组+链表+红黑树组成
  • 当挂在元素下面的数据过多时,查询性能降低,从JDK8开始后,当链表长度超过8的时候,自动转换为红黑树
  • 哈希值:是JDK根据对象的地址,按照某种规则算出来的int类型的数值
  • Object类的API:public int hashCode​():返回对象的哈希值
  • 对象的哈希值特点
    • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
    • 默认情况下,不同对象的哈希值是不同的

2.1 哈希表详细流程

Step1:创建一个默认长度16默认加载因子0.75的数组,数组名table
Step2:根据元素的哈希值数组的长度计算出应存入的位置
Step3:判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素, 则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组

JDK 7新元素占老元素位置,指向老元素
JDK 8中新元素挂在老元素下面

Step4:当数组存满到16*0.75=12时,就自动扩容,每次扩容原先的两倍

Ps:必须重写Object类的equals()和Hashcode()

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

   @Override
   public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;
       Student student = (Student) o;
       return age == student.age && name.equals(student.name);
   }

   @Override
   public int hashCode() {
       return Objects.hash(age, name);
   }
}

3 LinkedHashSet

  • 有序、不重复、无索引
  • 这里的有序指的是保证存储和取出的元素顺序一致

原理:底层数据结构是依然哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序

4 TreeSet

  • 可排序、不重复、无索引
  • 可排序:按照元素的大小默认升序(有小到大)排序
  • TreeSet集合底层是基于红黑树的数据结构实现排序的,增删改查性能都较好

注意:TreeSet集合是一定要排序的,可以将元素按照指定的规则进行排序

TreeSet集合默认的规则

  • 对于数值类型:Integer , Double,官方默认按照大小进行升序排序
  • 对于字符串类型:默认按照首字符的编号升序排序
  • 对于自定义类型,需要制定排序规则

方式一

  • 让自定义的类(如学生类)实现Comparable接口重写里面的compareTo方法来定制比较规则。
public class Apple implements Comparable<Apple>{
    private int weight;
    
    public Apple() {
    }

    public Apple(int weight) {
        this.weight = weight;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                '}';
    }

    /**
      方式一:类自定义比较规则
      o1.compareTo(o2)
     * @param o
     * @return
     */
    @Override
    public int compareTo(Apple o) {
        // 按照重量进行比较的
        return this.weight - o.weight ; // 升序
        return o.weight - this.weight ; // 降序
    }
}

方式二

  • TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象,来定制比较规则。

补充知识点:可变参数

  • 可变参数用在形参中可以接收多个数据。
  • 可变参数的格式:数据类型…参数名称
public static void main(String[] args) {
     sum(); // 1、不传参数
     sum(10); // 2、可以传输一个参数
     sum(10, 20, 30); // 3、可以传输多个参数
     sum(new int[]{10, 20, 30, 40, 50}); // 4、可以传输一个数组
}

    /**
       注意:一个形参列表中只能有一个可变参数,可变参数必须放在形参列表的最后面
     * @param nums
     */
public static void sum(  int...nums){
     // 注意:可变参数在方法内部其实就是一个数组。 nums
     System.out.println("元素个数:" + nums.length);
     System.out.println("元素内容:" + Arrays.toString(nums));
}

可变参数作用:

  • 接收参数非常灵活,方便。可以不接收参数,可以接收1个或者多个参数,也可以接收一个数组
  • 可变参数在方法内部本质上就是一个数组

注意事项:

  • 一个形参列表中可变参数只能有一个
  • 可变参数必须放在形参列表的最后面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值