• 集合(3)—— Set


    一、什么是Set?

    Set接口是Collection接口的子接口,是一种不允许重复元素的集合。

     

    二、HashSet

    • HashSet是Set的一个典型实现类,无序,不可重复,允许加入NULL,大多数时候使用Set就是使用这个类,HashSet按照Hash算法来存储元素,因此具备很好的存取和查找性能。
    • 其底层其实是一个数组,存在的意义是加快查询速度,我们知道一般的数组,元素在其中的索引位置都是随机的,元素的取值和位置之间没有关联关系,因此,在数组中查找特定的元素时,只能逐个比较,查找速度取决于比较的次数。但是在HashSet底层的数组中,索引和值之间存在确定的关系:index=hash(value),因此通过这个关系可以快速的找到元素或者索引。
    • 当在HashSet中存储元素时,首先调用该对象的hashCode()方法,获取hashCode值,根据这个值,找到对应位置,HashSet中不允许重复,判断方法是:先比较hashCode是否相同,不同就认为是不同对象,相同的话再比较equals方法,根据结果判断。
    • 每一个存储到哈希表中的对象,都要提供equals方法和hashCode方法实现,以判断是否是相同对象,对于HashSet,我们应该保证如果两个对象通过equals方法返回true,hashCode值也相同。

    三、LinkedHashSet

    LinkedHashSet是有序,不允许重复,允许加入NULL的集合。

    它也是以HashCode值来决定元素的存储位置,同时还使用了链表来维护元素的顺序,这就使得它按照插入的顺序有序排列。相比Hashset多维护了链表,因此性能略低于HashSet。

    四、TreeSet

    TreeSet是有序,不允许重复,不允许NULL的集合。底层使用红黑树算法,擅长范围查询。

    • 如果使用TreeSet的无参构造器新建一个TreeSet对象,要求存储其中的元素实现Comparable接口,所以在其中不能存入NULL
    • 必须存入相同类型的对象(默认会进行排序),否则会出现类型转换异常!一般使用泛型来进行限制。
    • 自然排序:要求被添加的参数对象必须实现Comparable接口,并且覆盖了compareTo(Object obj)方法:

      如果 this>obj ,返回1,

      如果 this=obj ,返回0,

      如果 this<obj ,返回-1。

      通过该方法定义的规则比较之后,按照升序排列。

    • 定制排序:创建TreeSet对象时,传入实现了Compartor接口的实现类,通过compare方法定义的规则进行定制排序(如倒序),要求该实现类的compare方法和equals方法具有一致性,即:compare方法中,两个对象相等时应该return 0。

    如下,按照money多少降序排列:

     1 package com.vi.collection.set;
     2 
     3 import java.util.Comparator;
     4 import java.util.TreeSet;
     5 
     6 public class TreeSetDemo {
     7     public static void main(String[] args) {
     8         Man m1 = new Man(1000);
     9         Man m2 = new Man(2000);
    10         Man m3 = new Man(3000);
    11         Man m4 = new Man(2500);
    12         TreeSet<Man> ts = new TreeSet<>(new Man(0));
    13         ts.add(m1);
    14         ts.add(m2);
    15         ts.add(m3);
    16         ts.add(m4);
    17         System.out.println(ts);
    18     }
    19 }
    20 
    21 class Man implements Comparator<Man> {
    22     double money;
    23 
    24     public int compare(Man m1, Man m2) {
    25         if (m2.money > m1.money)
    26             return 1;
    27         if (m2.money == m1.money)
    28             return 0;
    29         return -1;
    30     }
    31 
    32     public Man(double money) {
    33         this.money = money;
    34     }
    35 
    36     public String toString(){
    37         return money+" ";
    38     }
    39 
    40 }
    View Code

     五、对以上三种Set进行比较

    共同点:

    1.都不允许存入重复值

    2.都是线程不安全的(解决办法:使用Collections.synchronizedSet()方法)

    不同点:

    1.TreeSet不允许NULL值,HashSet和LinkedList可以存入空值

    2.HashSet是无序的底层采用哈希表算法,查询效率高,通过equals()和hashCode()共同判断对象是否相等,即要求存入的对象重写equals()和hashCode()保持一致性;

    LinkedList底层采用了哈希表和链表的结构,既保证了元素的添加顺序,也保证了查询效率,性能略低于HashSet;

    TreeSet不保证元素的添加顺序,但是会按照自然排序或定制规则对集合中元素进行排序,底层采用了红黑树算法(树结构比较适合范围查询)。

  • 相关阅读:
    我对Web开发相关技术的认识过程
    JavaScript、JSP和Java之间的关系
    中断处理中的save_all、restore_all和iret
    实验五:Linux操作系统是如何工作的?破解操作系统的奥秘
    java CPU的乱序执行
    java缓存行对齐(缓存行二)
    解决ojdbc6升级ojdbc8中文乱码问题
    Caused by: java.lang.ClassNotFoundException: com.alibaba.dubbo.common.Version
    springSecurity5 重定向登录页面后 报错:尝试清除 Cookie.net::ERR_TOO_MANY_REDIRECTS status:200
    java 工厂模式 从无到有-到简单工厂模式-到工厂方法模式-抽象工厂模式
  • 原文地址:https://www.cnblogs.com/blogforvi/p/11626793.html
Copyright © 2020-2023  润新知