Set

Set集合:类似于一个罐子,没有顺序,与Collection基本相同,没有提供任何额外方法,实际上Set就是Collection,只是行为有点不同,不能有重复元素。三个实现类:HashSet,TreeSet,EnumSet

HashSet:是Set接口的典型实现,大多数时候使用Set集合就是使用这个类,按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能

  特点:

    不能保证元素的排列顺序

    不是同步的,多个线程访问HashSet要通过代码来保证同步

    集合元素值可以是null

  当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()来得到该对象的hashCode值,根据该值决定对象在HashSet中的存储位置,即使equals返回true但hashCode不同也会存在不同位置,即可以添加成功。

  也就是说HashSet集合判断两个元素相等的标准是两个对象通过euqals方法比较相等,并且两个对象的hashCode()方法返回值也相等。所以这两个方法被重写时应该同时被重写,即equals同时code同

  HashSet中每个能存储元素的“ 槽位”(slot)通常被称为“桶”(bucket),如果有多个元素hashCode相同但equals不同,就需要在一个桶里放入多个元素,会导致性能下降

  hashCode重写规则:

    程序运行过程中,同一个对象多次调用hashCode方法返回值应该相同

    当两个对象通过equals方法比较返回true时,两个对象的hashCode也应该相同

    对象中用作equals方法比较标准的实例 变量,都应该用于计算hashCode的值

LinkedHashSet:是HashSet的子类,不同的是他同时使用链表来维护元素的次序,,按元素插入顺序存储,因此性能略低于HashSet,但在迭代访问Set里的全部元素时有很好的性能

TreeSet:是SortedSet接口的实现类,可以确保元素处于排序状态,与HashSet相比,TreeSet还提供了几个额外方法。first,last,lower(Object o),higher(o)。。。。

  TreeSet采用红黑树的数据结构来存储集合元素,支持两种排序方法:定制排序和自然排序

  自然排序:TreeSet调用集合元素的compareTo(Object o)来比较元素之间的大小关系,然后按升序排列

    java提供一个Comparable接口,接口里定义了compareTo(o)方法,返回一个整数值。因此当用TreeSet存元素时,该元素必须实现了Comparable接口,否则出ClassCastException异常

    存的第一个不会出,因为此时Set里为null,第二个会导致调用compareTo()而出异常。但取元素时,依然会出ClassCastException异常

    常用实现Comparable的类:BigDecimal,BigInteger以及所有数值类型对应的包装类,Character,Boolean,String,Date,Time

    大部分类实现compareTo(o)方法时,都把被比较对象转换成相同类型,所以,TreeSet应该添加同一个类的对象,否则引发ClassCastException

  TreeSet判断两个对象相同的唯一标准是compareTo方法返回0

  定制排序:通过Comparator接口,该接口包含一个int compare(T o1,T o2)方法用于比较o1和o2的大小,提供一个Comparator对象与TreeSet关联,Comparator是函数时接口,可以使用Lumbda代替Comparator对象:TreeSet t = new TreeSet((o1,o2)->{。。。。});

EnumSet:专门为枚举类型设计的集合类,该集合中的所有元素必须是指定枚举类型的枚举值,枚举类型在创建EunmSet时显式或隐式指定。是有序的,按枚举值在Enum类里的定义顺序决定

  EnumSet在内部按位向量的形式存储,这种形式非常紧凑,高效,因此EnumSet对象占用内存很小,运行效率很好,尤其是批量操作。

  不允许加入null元素,加入则抛出NullPointerException异常

  不是枚举值泽抛出ClassCastException

各个Set实现类的性能分析:

  HashSet和TreeSet是Set的两个典型实现,HashSet的性能总是比TreeSet好,特别是最常用的添加,查询元素等操作,因为TreeSet需要额外的红黑树算法来维护集合元素的次序,只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该用HashSet。HashSet的子类LinkedHashSet性能比HashSet差一点,但遍历性能更好。EunmSet是所有Set里性能最好的,但只能用于枚举类型的枚举值。

  HashSet,TreeSet,EnumSet都是线程不安全的,多线程访问是需要手动保证同步,通常使用Collections工具类的synchronizedSortedSet方法来包装该Set集合:

    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

posted on 2017-06-15 14:28  zawjdbb  阅读(231)  评论(0编辑  收藏  举报

导航