TreeSet 树结构
-
特点:
- 有序
-
内容要求:
- 1.包装类
- 2.引用类型(必须提前写好排序规则)
-
TreeSet中维护了一个TreeMap
-
public V put(K key, V value) {//TreeMap的添加方法 Entry<K,V> t = root;//将根节点备份 if (t == null) {//判断是否是第一次添加 compare(key, key); // type (and possibly null) check root = new Entry<>(key, value, null);//直接将对象封装成Entry对象,赋给根节点 size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator;//将定制排序的对象进行备份 if (cpr != null) {//是否有定制排序 //从根节点就行对比,直到有一个分叉是null为止,找到当前对象添加的位置 do { parent = t; cmp = cpr.compare(key, t.key);//对比大小 if (cmp < 0) t = t.left;//小于走左侧 else if (cmp > 0) t = t.right;//大于走右侧 else return t.setValue(value); } while (t != null); }else { //说明没有定制排序 ---> 默认就采用自然排序 if (key == null)//抛空指针异常 throw new NullPointerException(); @SuppressWarnings("unchecked") Comparable<? super K> k = (Comparable<? super K>) key;//将当前对象强转为Comparable //依然是从根节点进行对比大小,直到找到自己所在的位置为止 do { parent = t; cmp = k.compareTo(t.key);//对比大小 if (cmp < 0) t = t.left;//小于走左侧 else if (cmp > 0) t = t.right;//大于走右侧 else//说明在当前树节点中找到和当前对象相同的数据了,则对value值进行覆盖 return t.setValue(value); } while (t != null); } Entry<K,V> e = new Entry<>(key, value, parent);//将当前对象封装成一个Entry对象 if (cmp < 0) parent.left = e;//将当前Entry对象放在parent的左侧 else parent.right = e;//将当前Entry对象放在parent的右侧 fixAfterInsertion(e); size++; modCount++; return null; }
-
2、
- TreeSet无序的原因
- 有一个大小排序机制
- Comparable --> int compareTo(Object obj)
- Comparator --> int compare(Object o1,Object o2)
- 大于返回正数、等于返回0、小于负数
- 有一个大小排序机制
- TreeSet不可重复的原因
- Comparable --> int compareTo(Object obj)
- Comparator --> int compare(Object o1,Object o2)
- 如果返回的是0,则进行value值的覆盖
- TreeSet无序的原因
-
3、 面试题
- a. HashSet如何实现的无序和不可重复
- 利用长度&hashcode决定下标
- 利用hashcode和equals判断重复
- b. TreeSet如何实现的无序(无序是指不以添加顺序为输出顺序)和不可重复
- 有定制排序机制(Comparable --> int compareTo(Object obj)或Comparator --> int compare(Object o1,Object o2))
- 排序是发现相同的就用新的覆盖掉旧的
- c. TreeSet中如果定制排序和自然排序同时存在,以谁为准?
- 定制排序为准(代码中先判断了是否存在定制排序,如果不存在在进入自然排序的方法)
- a. HashSet如何实现的无序和不可重复