TreeSet源码分析(JDK1.8)

成员变量

1、m
/**
 * TreeSet底层是以TreeMap来储存数据的,key为add()中的元素,value为PRESENT值
 */
private transient NavigableMap<E,Object> m;
2、PRESENT
/**
 * 空的Object对象,作为TreeMap中的value值
 */
private static final Object PRESENT = new Object();

构造方法

1、TreeSet():无参构造方法
/**
 * 无参构造方法,创建一个TreeSet对象
 */
public TreeSet() {
  this(new TreeMap<E,Object>());
}

/**
 * 创建一个TreeMap对象
 */
TreeSet(NavigableMap<E,Object> m) {
  this.m = m;
}
2、TreeSet(Comparator<? super E> comparator):指定比较器
/**
 * 指定比较器创建一个TreeMap对象
 */
public TreeSet(Comparator<? super E> comparator) {
  this(new TreeMap<>(comparator));
}
3、TreeSet(Collection<? extends E> c):在初始化时构造一组包含指定集合中的元素的TreeSet对象
/**
 * 先创建一个TreeMap对象,再添加指定集合中的元素
 */
public TreeSet(Collection<? extends E> c) {
  this();
  addAll(c);
}
4、TreeSet(SortedSet s):在初始化时构造一组包含指定集合和指定比较器中的元素的TreeSet对象
/**
 * 指定比较器创建一个TreeMap对象,再添加指定集合中的元素
 */
public TreeSet(SortedSet<E> s) {
  this(s.comparator());
  addAll(s);
}

常用方法

1、add(E e)

add(E e)执行原理:

调用TreeMap中的put()方法进行添加元素

add(E e)源码:

/**
 * 调用TreeMap中的put()方法进行添加元素
 */
public boolean add(E e) {
  return m.put(e, PRESENT)==null;
}
2、remove(Object o)

remove(Object o)执行原理:

调用TreeMap中的remove()方法来删除TreeSet中的元素

remove(Object o)源码:

/**
 * 调用TreeMap中的remove()方法来删除TreeSet中的元素
 */
public boolean remove(Object o) {
  return m.remove(o)==PRESENT;
}
3、removeAll(Collection<?> c)

removeAll(Collection<?> c)执行原理:

1、调用TreeSet的父类AbstractSet中的removeAll(Collection<?> c)方法

2、循环删除当前TreeSet对象的在传入集合对象中存在的元素

removeAll(Collection<?> c)源码:

/**
 * 循环删除当前TreeSet对象的在传入集合对象中存在的元素
 */
public boolean removeAll(Collection<?> c) {
  Objects.requireNonNull(c);
  boolean modified = false;

  // 如果当前TreeSet对象的实际元素个数>传入的集合对象的实际元素个数
  if (size() > c.size()) {
    for (Iterator<?> i = c.iterator(); i.hasNext(); )
      modified |= remove(i.next());
  }
  
  // 如果当前TreeSet对象的实际元素个数<传入的集合对象的实际元素个数
  else {
    for (Iterator<?> i = iterator(); i.hasNext(); ) {
      if (c.contains(i.next())) {
        i.remove();
        modified = true;
      }
    }
  }
  return modified;
}
4、contains(Object o)

contains(Object o)执行原理:

调用TreeMap中的contains()方法判断TreeSet中是否包含此key

contains(Object o)源码:

/**
 * 调用TreeMap中的contains()方法判断TreeSet中是否包含此key
 */
public boolean contains(Object o) {
  return m.containsKey(o);
}
5、containsAll(Collection<?> c)

containsAll(Collection<?> c)执行原理:

1、调用TreeSet的父类AbstractSet的父类AbstractCollection中的containsAll(Collection<?> c)方法

2、循环判断传入的集合中的元素是否包含在TreeSet集合中

containsAll(Collection<?> c)源码:

/**
 * 循环判断传入的集合中的元素是否包含在TreeSet集合中
 */
public boolean containsAll(Collection<?> c) {
  for (Object e : c)
    if (!contains(e))
      return false;
  return true;
}
6、retainAll(Collection<?> c)

retainAll(Collection<?> c)执行原理:

1、调用TreeSet的父类AbstractCollection中的retainAll(Collection<?> c)方法

2、迭代器遍历,如果TreeSet集合中的元素不在传入的集合对象之中,那么就删除

retainAll(Collection<?> c)源码:

/**
 * 迭代器遍历,如果TreeSet集合中的元素不在传入的集合对象之中,那么就删除
 */
public boolean retainAll(Collection<?> c) {
  Objects.requireNonNull(c);
  boolean modified = false;
  
  // 迭代器遍历当前TreeSet集合中的元素
  Iterator<E> it = iterator();
  while (it.hasNext()) {
    // 如果TreeSet集合中的元素不在传入的集合对象之中,那么就删除
    if (!c.contains(it.next())) {
      it.remove();
      modified = true;
    }
  }
  return modified;
}
7、isEmpty()

isEmpty()执行原理:

调用TreeMap中的isEmpty()方法判断TreeSet中是否包含元素

isEmpty()源码:

/**
 * 调用TreeMap中的isEmpty()方法判断TreeSet中是否包含元素
 */
public boolean isEmpty() {
  return m.isEmpty();
}
8、iterator()

iterator()执行原理:

调用TreeMap中的内部类KeySet中的iterator()方法

iterator()源码:

/**
 * 调用TreeMap中的内部类KeySet中的iterator()方法
 */
public Iterator<E> iterator() {
  return m.navigableKeySet().iterator();
}
9、equals(Object o)

equals(Object o)执行原理:

1、调用TreeSet的父类AbstractSet中的equals(Object o)方法

2、底层通过调用containsAll()方法来进行判断的

equals(Object o)源码:

/**
 * 判断传入的对象是否和TreeSet对象一致
 */
public boolean equals(Object o) {
  // 当传入对象为当前对象时
  if (o == this)
    return true;

  // 当传入对象没有实现Set接口时
  if (!(o instanceof Set))
    return false;
  
  // 当传入对象的实际元素个数不等时
  Collection<?> c = (Collection<?>) o;
  if (c.size() != size())
    return false;
  
  // 调用containsAll()来判断传入的集合元素是否都在TreeSet对象中
  try {
    return containsAll(c);
  } catch (ClassCastException unused)   {
    return false;
  } catch (NullPointerException unused) {
    return false;
  }
}
10、size()

size()执行原理:

调用TreeMap中的size()方法来获取TreeSet中实际元素的个数

size()源码:

/**
 * 调用TreeMap中的size()方法来获取TreeSet中实际元素的个数
 */
public int size() {
  return m.size();
}
11、clear()

clear()执行原理:

调用TreeMap中的clear()方法进行清除TreeMap中所有的元素

clear()源码:

/**
 * 调用TreeMap中的clear()方法进行清除TreeMap中所有的元素
 */
public void clear() {
  m.clear();
}
12、comparator()

comparator()执行原理:

调用TreeMap中的comparator()方法获取指定的比较器

comparator()源码:

/**
 * 调用TreeMap中的comparator()方法获取指定的比较器
 */
public Comparator<? super E> comparator() {
  return m.comparator();
}

总结

  • TreeSet底层是使用TreeMap来存储数据,key值为TreeSet中的数据,value值为一个空的Object对象
  • TreeSet的方法大多是通过调用TreeMap中的方法来实现的
  • TreeSet和TreeMap一样,都是线程不安全的集合类
  • TreeSet和TreeMap一样,有两种方式定义key的比较规则,优先使用指定的构造器进行比较key
    • key实现Comparable接口重写compareTo方法
    • 通过TreeSet的构造方法指定构造器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值