Collection---Set

Set

  • TreeSet:基于红黑树实现,支持有序性操作,例如根据一个范围查找元素的操作。但是查找效率不如 HashSet,HashSet 查找的时间复杂度为 O(1),TreeSet 则为 O(logN)。
  • HashSet:基于哈希表实现,支持快速查找,但不支持有序性操作。并且失去了元素的插入顺序信息,也就是说使用 Iterator 遍历 HashSet 得到的结果是不确定的。
  • LinkedHashSet:具有 HashSet 的查找效率,并且内部使用双向链表维护元素的插入顺序。

一、HashSet源码分析

1.成员变量

// 底层使用HashMap来保存HashSet的元素
private transient HashMap<E,Object> map;
// Set使用的只是Map的Key,所以这里定义一个静态常量充当value
private static final Object PRESENT = new Object();

关于value的使用:为什么不用null?

因为HashSet中的很多方法都是依赖HashMap实现,而这些方法需要通过返回null来判断是否执行成功,如果value使用null,那么就无法分清方法返回的null的真正含义了

2.构造方法

  1. 无参构造
public HashSet() {
        map = new HashMap<>();
    }
  1. 指定初始容量(默认加载因子0.75)
public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }
  1. 指定初始容量和加载因子
public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }
  1. 指定Collection
public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    // 调用AbstractCollection中的方法遍历添加集合元素
        addAll(c);
    }

// 该方法是AbstractCollection默认实现的
public boolean addAll(Collection<? extends E> c) {
        boolean modified = false;
        for (E e : c)
            if (add(e))
                modified = true;
        return modified;
    }
  1. 不公开的一个构造方法(default修饰)
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }
/*该方法不对外公开,实际上是提供给LinkedHashSet使用的,而第三个参数dummy是无意义的,只是为了区分其他构造方法。 */

3.核心方法

1)添加方法

public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

2)查找方法

  • contains(Object)
public boolean contains(Object o) {
        return map.containsKey(o);
    }

3)删除方法

  • clearn()
public void clear() {
        map.clear();
    }
  • remove(Object)
 public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

总结

  1. HashSet虽然实现的是Set接口,但是它的底层全部是依赖于HashMap的
  2. HashSet没有get方法,获取元素只能通过遍历(迭代器、for、增强for)
  3. HashSet不允许有重复元素(Map的key唯一性)
  4. 不保证元素的顺序(HashMap散列存储)
  5. 允许使用 1个null 元素(Map允许一个null键)
  6. 非线程安全

二、TreeSet

博客推荐:TreeSet源码分析-java8

总结

  1. TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。它继承于AbstractSet抽象类,实现了NavigableSet, Cloneable, java.io.Serializable接口。
  2. TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
  3. TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序或者根据创建TreeSet 时提供的 Comparator 进行排序。
  4. 非线程安全
  5. 不允许有null值

三、LinkedHashSet

LinkedHashSet继承自HashSet,但是是基于LinkedHashMap实现的(前面说过它调用的是HashSet中不公开的构造函数,构建了一个LinkedHashSet)

它的体系结构如图:
Collection---Set_第1张图片

你可能感兴趣的:(Collection---Set)