TreeSet是使用树状结构来存储set接口的实现类,它按照从小到大的顺序排列,所以TreeSet在一般的Set集合无序不可重复的基础上变为有序不可重复,由于是树状结构存储,所以TreeSet遍历速度非常快,在存储大量数据并需要检索的情况下TreeSet是一个非常好的选择。
TreeSet实现了NavigableSet接口,该接口扩展了SortSet,具有了给定搜索目标报告最近匹配项的导航方法。方法 lower
、floor
、ceiling
和 higher
分别返回小于、小于等于、大于等于、大于给定元素的元素,如果不存在这样的元素,则返回 null
。同时还提供了两种遍历方法如下,此外还定义了pollFirst,pollLast两种方法,他们可以移除最大或最小元素,由于在导航方法中null值的插入式不确定的因此Navigable接口不允许插入空值,所以当我们尝试向TreeSet中插入空值时会出现空指针异常。
//升序遍历
Iterator<Integer> iterator = tree.iterator();
while(iterator.hasNext()){
log.info(iterator.next());
}
//降序遍历
Iterator<Integer> iterator2 = tree.descendingIterator();
while(iterator2.hasNext()){
log.info(iterator2.next());
}
由于TreeSet实现了Set接口,在存值的时候使用equals和hashcode来判断是否重复,而在位置的判断则是通过实现了Comparable接口的compareTo来判断的,所以当我们要指定TreeSet的排序时只需要更改其compareTo方法的书写即可。
@Test
public void testTreeSetSort(){
TreeSet<Student> treeSet = new TreeSet<>();
treeSet.add(new Student(6,"张三6"));
treeSet.add(new Student(5,"张三5"));
treeSet.add(new Student(4,"张三4"));
treeSet.add(new Student(3,"张三3"));
treeSet.add(new Student(2,"张三2"));
treeSet.add(new Student(1,"张三1"));
log.info(treeSet);
}
class Student implements Comparable<Student>{
private int id;
private String name;
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public int compareTo(Student o) {
return this.id-o.id;
}
private TestTreeSet getOuterType() {
return TestTreeSet.this;
}
}
TreeSet不是线程安全的,如果多个线程同时访问集合,其中一个线程修改了set那么他们必须在外部添加同步,