Java集合

Set集合

Set集合中的元素是无序的(这里的无序指的是元素的放入顺序),另外Set集合中不能包含重复的元素。主要的Set集合类包括:HashSetTreeSetEnumSet

HashSet类

HashSet集合利用哈希表存储数据,哈希表存储时会涉及到元素冲突问题,这里解决冲突使用的是拉链法,也就是将哈希码相同的元素放在一个链表上。在向该集合插入元素时,需要先计算元素的hashcode确定元素的存储位置,然后在通过equals()方法判断元素是否与已有元素重复。因此,对于需要放入Set集合中的对象需要重写同时hashCode()和'equals()'方法。

HashSet的特点:

  • 不保证元素的排列顺序
  • HashSet是线程不安全的
  • 元素的值可以为null
public static void testHashSet() {
    HashSet<String> set = new HashSet<>();
    set.add("aaa");
    set.add("bbb");
    set.add("ccc");
    set.remove("aaa");
    set.add("aaa");
    Iterator<String> it = set.iterator();
    System.out.println("testHashSet: ");
    while (it.hasNext()) {
        System.out.print(it.next() + " ");
    }
    System.out.println();
}

移除元素aaa后再重新添加,输出次序不变,说明HashSet元素顺序与插入顺序无关。

LinkedHashSet类

LinkedHashSet继承了HashSet类,同样使用哈希码决定元素的存储位置,但是它采用链表维护元素的插入次序,因此它是有序的Set集合。其余性质与HashSet一致。

public static void testLinkedHashSet() {
    LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
    linkedHashSet.add("aaa");
    linkedHashSet.add("bbb");
    linkedHashSet.add("ccc");
    linkedHashSet.remove("aaa");
    linkedHashSet.add("aaa");
    Iterator<String> it = linkedHashSet.iterator();
    System.out.println("testLinkedHashSet: ");
    while (it.hasNext()) {
        System.out.print(it.next() + " ");
    }
}

移除元素aaa后再重新添加,aaa最后输出,说明LinkedHashSet维护了元素的插入次序。

TreeSet类

TreeSetSortedSet接口的实现类,该集合中的元素是按照元素的大小来排序的,TreeSet采用红黑树的数据结构来存储集合中的元素,不允许插入null。对于元素的大小判定可以按照自然排序也可以采用自定义的排序规则。

public static void testTreeSet() {
    TreeSet treeSet = new TreeSet();
    treeSet.add(7);
    treeSet.add(1);
    treeSet.add(-4);
    treeSet.add(19);
    treeSet.add(12);
    for (Object num : treeSet) {
        System.out.println(num);
    }
}

EnumSet类

EnumSet是专为枚举类设计的集合类,EnumSet集合中的元素必须是指定的枚举类中的值,EnumSet集合中元素的存储顺序与相应的枚举类中的元素顺序一致,不允许包含null值。

总结

  • 通常情况下,只有希望集合中的元素有序(不是指插入顺序)时才考虑使用TreeSet毕竟维护红黑树结构需要一定的开销,另外根据对集合的常用操作来选择使用HashSet还是LinkedHashSet,如果需要对集合经常插入和删除则采用HashSet,因为LinkedHashSet需要维护一个链表,也因此LinkedHashSet的遍历更快。

  • 虽然EnumSet是所有Set中性能最好的,但是由于它只能用于存储枚举类中的元素,限制了它的使用场景。
  • 这里所有的Set类都是线程不安全的。

上一篇:集合家族——HashSet


下一篇:Java 之 LinkedHashSet 集合