TreeSet简介
TreeSet是无序的集合容器,但也有排序的规则,元素实现Comparable接口,使其具有排序能力, TreeSet按照排序规则,进行排序,也通过这个接口实现元素唯一性;TreeSet不像HashSet,HashSet需要重写hashCode()和equals()方法,保证数据唯一性,hashSet底层存储结构是hash表,TreeSet是二叉树;
源码分析
TreeSet代码分析
1. TreeSet调用add方法,存储元素
2. 底层调用方法如下
put()方法时TreeMap的方法,存贮采用二叉树形式。当返回值为null时,表示将数据存储成功了,如果么有则返回的是以前的原始集合。
- 如果集合为空,第一次呢存储元素,则进行一下元素与null的比较
- 如果集合中传入比较器,则通过比较器比较,采用二叉树的中序遍历
这是集合中不存在这个对象,新建对象,保存到集合中。关于存放位置,如果返回值小于0,存放在二叉树的左边,否则存在在二叉树的右边。
采用接口Comparable接口中的方法,原理相同。
注意:
比较过程底层是中序遍历,遍历过程是采用前序遍历。
自定义TreeSet实现
package eTree.treeSetPack;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import eTree.Node;
/**
* 自定义TreeSet
*
* @author mahao
* @date: 2019年3月22日 下午9:31:28
* @param <E>
* 实现Comparable接口的类
*/
public class TreeSet<E extends Comparable<E>> implements Iterable<E> {
Node<E> root;
public E add(E e) {
Node<E> node = new Node(e, null);
if (root == null) {
root = node;
return null;
} else {
return work(root, e);
}
}
private E work(Node<E> node, E e) {
E n = (E) node.data;
int flag = e.compareTo(n);
if (flag > 0) {
if (node.right == null) {
node.right = new Node<>(e, null);
return null;
}
return work(node.right, e);
} else if (flag < 0) {
if (node.left == null) {
node.left = new Node<>(e, null);
return null;
}
return work(node.left, e);
} else {
// System.out.println("数据相同,舍弃---数据相同");
E oldE = (E) node.data;
node.data = e;
return oldE;
}
}
@Override
public Iterator<E> iterator() {
return new Iter();
}
// 中序遍历
private class Iter implements Iterator<E> {
List<E> list = null;
int i = 0;
public Iter() {
list = new ArrayList<E>();
work(list, root);
}
private void work(List list, Node node) {
if (node != null) {
work(list, node.left);
list.add(node.data);
work(list, node.right);
}
}
@Override
public boolean hasNext() {
return !(i == list.size());
}
@Override
public E next() {
return list.get(i++);
}
}
}
//添加元素
package eTree.treeSetPack;
/**
* TreeSet中存储的对象,按照年龄降序排序, 如果年龄相同,判断名字是否相同
*
* @author mahao
* @date: 2019年3月3日 上午11:48:56
*/
public class User implements Comparable<User> {
private String name;
private int age;
private String str;
@Override
/**
* 实现compareTo方法,使具有排序的能力 1 - 当前对象大 0 - 两对象相等 -1 - 被计较对象大;
*/
public int compareTo(User o) {
if (null == o)
throw new NullPointerException();
System.out.println("比较过程--" + this.name + "--compareTo--" + o.getName());
int num = this.age - o.getAge();
if (num == 0)// 年龄相同时,比较姓名是否一样,字符串默认实现了Comparable接口
return this.name.compareTo(o.getName());
return num;
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User(String name, int age, String str) {
this.name = name;
this.age = age;
this.str = str;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
}
//测试
package eTree.treeSetPack;
import java.util.Iterator;
/**
* 二叉树
*
* @author mahao
* @date: 2019年3月22日 下午6:47:37
*/
public class MainClass2 {
public static void main(String[] args) {
TreeSet<User> set = new TreeSet<User>();
set.add(new User("11", 5,"flag--11"));
set.add(new User("16", 1,"flag--16"));
set.add(new User("11", 7,"flag--11"));
set.add(new User("14", 1,"flag--14"));
set.add(new User("16", 1,"flag--18"));
Iterator<User> it = set.iterator();
while(it.hasNext()) {
User u = it.next();
System.out.println(u.getName()+"---"+u.getAge()+"-----"+u.getStr());
}
}
}
结果--------
比较过程--16--compareTo--11
比较过程--11--compareTo--11
比较过程--14--compareTo--11
比较过程--14--compareTo--16
比较过程--16--compareTo--11
比较过程--16--compareTo--16
14---1-----flag--14
16---1-----flag--18
11---5-----flag--11
11---7-----flag--11