常见的Set集合:HashSet,TreeSet,LinkedHashSet
三者间的联系:
(1)HashSet、TreeSet是Set的两个典型实现,LinkedHashSet是HashSet的实现类。简单来说,HashSet的性能总是比TreeSet好(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序。只有当需要一个排序的Set时,才应该使用TreeSet,否则都应该使用HashSet。
(2)对于LinkedHashSet,对于普通的插入、删除操作,LinkedHashSet比HashSet要略微慢一点,这是因为维护链表所带来的额外的开销造成的,但由于有了链表,遍历LinkedHashSet会更快。
(3)还有一点需要指出的是:Set的三个实现类(HashSet、TreeSet和EnumSet)都是线程不安全的,如果有多个线程同时访问一个Set集合,并且有超过一个线程修改了该Set集合,则必须手动保证Set集合的同步性。通常可以通过Collections工具类的sysnchronizedSortedSet方法来“包装”该Set集合。所以,最好在创建的时候进行,以防止对Set集合的意外非同步访问。
三者间的区别:
1 .HashSet
HashSet是基于HashMap来实现的,操作很简单,更像是对HashMap做了一次“封装”,而且只使用了HashMap的key来实现各种特性。
HashSet是通过HashMap实现,整个HashSet的核心就是HashMap。HashMap中的键作为HashSet中的值,HashMap中的值通过创建一个假的value来实现。
不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
HashSet不是同步的。如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程同时修改了HashSet集合时,则必须通过代码来保证同步。
集合元素值可以是null。
HashSet类判断两个元素是否相等,需要两个条件,第一个条件:equals()的结果为true,第二个条件:hashCode()的值相等,即对应的元素的hashCode码要相同。
HashSet集合的优点:
它可以通过一个对象快速查找到集合中的对象。hash算法的价值在于查找速度很快:它是通过将对象转变为对应的hashCode值,然后按照hashCode值在桶中对应位置取出该元素。
2 .TreeSet
该类实现的接口:Serializable, Cloneable, Iterable, Collection, NavigableSet, Set, SortedSet
TreeSet原理:
TreeSet是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态。
TreeSet并不是根据元素的插入顺序进行排序的,而是根据元素的实际值大小来进行排序。
与HashSet集合采用的hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素。其中,TreeSet支持两种排序方法:自然排序和定制排序,在默认情况下,TreeSet采用自然排序。
使用该集合的类必须实现Comparable接口中的compare To()方法,因为该类是有序的。
3 .LinkedHashSet
该类实现的接口:Serializable, Cloneable, Iterable, Collection, Set
LinkedHashSet原理:
LinkedHashSet是HashSet接口的实现类,LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但他同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。也就是说,当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按照元素的添加顺序来访问集合里的元素。
LinkedHashSet需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时将会有很好的性能,因为它以链表来维护内部的顺序。
虽然LinkedHashSet使用了链表记录集合元素的添加顺序,但LinkedHashSet依然是HashSet,因此它仍然是不允许集合元素重复。
测试案例:
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class day16 {
public static void main(String[] args) {
Set<String> hashSet = new HashSet<>();
Set<String> treeSet = new TreeSet<>();
Set<String> linkedHashSet = new LinkedHashSet<>();
Set<Integer> hashSet2 = new HashSet<>();
Set<Integer> treeSet2 = new TreeSet<>();
Set<Integer> linkedHashSet2 = new LinkedHashSet<>();
Set<String> hashSet3 = new HashSet<>();
Set<String> treeSet3 = new TreeSet<>();
Set<String> linkedHashSet3 = new LinkedHashSet<>();
List<String> list1 = Arrays.asList("黄","河","之","水","天","上","来","奔","流","到","海","不","复","回",
"黄","河","之","水","天","上","来","奔","流","到","海","不","复","回");
List<Integer> list2 = Arrays.asList(2 , 1 , 4 , 3 , 6 , 5 ,7 , 14, 13 ,12 , 11 ,10 , 9 , 8,
2 , 1 , 4 , 3 , 6 , 5 ,7 , 8 , 9 ,10 , 11 ,12 , 13 , 14);
List<String> list3 = Arrays.asList("2" , "1" , "4" , "3" , "6" , "5" ,"7" , "14", "13" ,"12" , "11" ,"10" , "9" , "8",
"2" , "1" , "4" , "3" , "6" , "5" ,"7" , "8" , "9" ,"10" , "11" ,"12" , "13" , "14");
hashSet.addAll(list1);
System.out.println("hashSet1:"+hashSet);
hashSet2.addAll(list2);
System.out.println("hashSet2:"+hashSet2);
hashSet3.addAll(list3);
System.out.println("hashSet3:"+hashSet3);
System.out.println("------------------------------------------------");
treeSet.addAll(list1);
System.out.println("treeSet1:"+treeSet);
treeSet2.addAll(list2);
System.out.println("treeSet2:"+treeSet2);
treeSet3.addAll(list3);
System.out.println("treeSet3:"+treeSet3);
System.out.println("------------------------------------------------");
linkedHashSet.addAll(list1);
System.out.println("linkedHashSet1:"+linkedHashSet);
linkedHashSet2.addAll(list2);
System.out.println("linkedHashSet2:"+linkedHashSet2);
linkedHashSet3.addAll(list3);
System.out.println("linkedHashSet3:"+linkedHashSet3);
System.out.println("-------------------------------------------------");
}
}
测试输出:
hashSet1:[流, 黄, 来, 天, 上, 之, 不, 复, 到, 河, 水, 奔, 海, 回]
hashSet2:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
hashSet3:[11, 12, 13, 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
--------------------------------------------------------
treeSet1:[上, 不, 之, 到, 回, 复, 天, 奔, 来, 水, 河, 流, 海, 黄]
treeSet2:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
treeSet3:[1, 10, 11, 12, 13, 14, 2, 3, 4, 5, 6, 7, 8, 9]
--------------------------------------------------------
linkedHashSet1:[黄, 河, 之, 水, 天, 上, 来, 奔, 流, 到, 海, 不, 复, 回]
linkedHashSet2:[2, 1, 4, 3, 6, 5, 7, 14, 13, 12, 11, 10, 9, 8]
linkedHashSet3:[2, 1, 4, 3, 6, 5, 7, 14, 13, 12, 11, 10, 9, 8]
--------------------------------------------------------