Set集合与Collection的方法相同(Collection方法可以查看api),由于Set集合不允许存储相同的元素,所以如果把两个相同元素添加到同一个Set集合,则添加操作失败,新元素不会被加入,add()方法返回false。代码示例:
HashSet具有如下特点:
?不能保证元素的顺序。
?HashSet不是线程同步的,如果多线程操作HashSet集合,则应通过代码来保证其同步。
?集合元素值可以是null。
HashSet存储原理如下:
当向HashSet集合存储一个元素时,HashSet会调用该对象的hashCode()方法得到其hashCode值,然后根据hashCode值决定该对象的存储位置。HashSet集合判断两个元素相等的标准是(1)两个对象通过equals()方法比较返回true;(2)两个对象的hashCode()方法返回值相等。因此,如果(1)和(2)有一个不满足条件,则认为这两个对象不相等,可以添加成功。如果两个对象的hashCode()方法返回值相等,但是两个对象通过equals()方法比较返回false,HashSet会以链式结构将两个对象保存在同一位置,这将导致性能下降,因此在编码时应避免出现这种情况。
HashSet查找原理如下:
基于HashSet以上的存储原理,在查找元素时,HashSet先计算元素的HashCode值(也就是调用对象的hashCode方法的返回值),然后直接到hashCode值对应的位置去取出元素即可,这就是HashSet速度很快的原因。
重写hashCode()方法的基本原则如下:
?在程序运行过程中,同一个对象的hashCode()方法返回值应相同。
?当两个对象通过equals()方法比较返回true时,这两个对象的hashCode()方法返回值应该相等。
?对象中用作equals()方法比较标准的实例变量,都应该用于计算hashCode值。
2)LinkedHashSet类
LinkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的hashCode值来决定元素的存储位置。但它使用链表维护元素的次序,元素的顺序与添加顺序一致。由于LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet,但在迭代访问Set里的全部元素时由很好的性能。
3)TeSet类
TeSet时SortedSet接口的实现类,TeSet可以保证元素处于排序状态,它采用红黑树的数据结构来存储集合元素。TeSet支持两种排序方法:自然排序和定制排序,默认采用自然排序。
?自然排序
TeSet会调用集合元素的
?定制排序
想要实现定制排序,需要在创建TeSet集合对象时,提供一个Comparator对象与该TeSet集合关联,由Comparator对象负责集合元素的排序逻辑。
4)EnumSet类
EnumSet是一个专为枚举类设计的集合类,不允许添加null值。EnumSet的集合元素也是有序的,它以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
5)各Set实现类的性能分析
HashSet的性能比TeSet的性能好(特别是添加,查询元素时),因为TeSet需要额外的红黑树算法维护元素的次序,如果需要一个保持排序的Set时才用TeSet,否则应该使用HashSet。
LinkedHashSet是HashSet的子类,由于需要链表维护元素的顺序,所以插入和删除操作比HashSet要慢,但遍历比HashSet快。
List集合
List集合代表一个有序、可重复集合,集合中每个元素都有其对应的顺序索引。List集合默认按照元素的添加顺序设置元素的索引,可以通过索引(类似数组的下标)来访问指定位置的集合元素。
实现List接口的集合主要有:ArrayList、LinkedList、Vector、Stack、Iterator接口和ListIterator接口。
Map接口采用键值对MapK,V的存储方式,保存具有映射关系的数据,因此,Map集合里保存两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value,key和value可以是任意引用类型的数据。key值不允许重复,可以为null。如果添加key-value对时Map中已经有重复的key,则新添加的value会覆盖该key原来对应的value。常用实现类有HashMap、LinkedHashMap、TeMap等。
Map常见方法如下:
1)HashMap与Hashtable
HashMap与Hashtable是Map接口的两个典型实现,它们之间的关系完全类似于ArrayList与Vertor。HashTable是一个古老的Map实现类,它提供的方法比较繁琐,目前基本不用了,HashMap与Hashtable主要存在以下两个典型区别:
?HashMap是线程不安全,HashTable是线程安全的。
?HashMap可以使用null值最为key或value;Hashtable不允许使用null值作为key和value,如果把null放进HashTable中,将会发生空指针异常。
为了成功的在HashMap和Hashtable中存储和获取对象,用作key的对象必须实现hashCode()方法和equals()方法。
HashMap工作原理如下:
HashMap基于hashing原理,通过put()和get()方法存储和获取对象。当我们将键值对传递给put()方法时,它调用建对象的hashCode()方法来计算hashCode值,然后找到bucket位置来储存值对象。当获取对象时,通过建对象的equals()方法找到正确的键值对,然后返回对象。HashMap使用链表来解决碰撞问题,当发生碰撞了,对象将会存储在链表的下一个节点中。
2)LinkedHashMap实现类
LinkedHashMap使用双向链表来维护key-value对的次序(其实只需要考虑key的次序即可),该链表负责维护Map的迭代顺序,与插入顺序一致,因此性能比HashMap低,但在迭代访问Map里的全部元素时有较好的性能。
3)Properties
Properties类时Hashtable类的子类,它相当于一个key、value都是String类型的Map,主要用于读取配置文件。
4)TeMap实现类
TeMap是SortedMap的实现类,是一个红黑树的数据结构,每个key-value对作为红黑树的一个节点。TeMap存储key-value对时,需要根据key对节点进行排序。TeMap也有两种排序方式:
?自然排序:TeMap的所有key必须实现Comparable接口,而且所有的key应该是同一个类的对象,否则会抛出ClassCastException。
?定制排序:创建TeMap时,传入一个Comparator对象,该对象负责对TeMap中的所有key进行排序。
5)各Map实现类的性能分析
?HashMap通常比Hashtable(古老的线程安全的集合)要快
?TeMap通常比HashMap、Hashtable要慢,因为TeMap底层采用红黑树来管理key-value。
?LinkedHashMap比HashMap慢一点,因为它需要维护链表来爆出key-value的插入顺序。