java set TreeSet详解

TreeSet 是sortedSet的唯一实现类,正如SortedSet名字暗示,TreeSet可以让集合元素处在排好序的状态。

与HashSet相比,TreeSet还额外提供了以下的方法(列出来,混个脸熟:)

SortedSet subSet(Object  fromElement,Object toElement) :返回这个Set的子集合,范围从fromElement(包含)到toElement(不包含)

SortedSet headSet(Object toElement):返回这个Set的子集合,范围小于toElement的子集合 

SortedSet tailSet(Object fromElement):返回这个Set的子集合,范围大于或等于fromElement的子集合 

Object first(): 返回这个Set第一个元素 

Object last():返回这个Set最后一个元素

Object lower(Object e):返回小于指定元素的集合里最大的那个元素 

Object higher(Object e):返回大于指定元素的集合里最小的那个元素     

【以上参考元素都不需要是集合里的

 总结一下,最后四个方法就是找到集合里的第一个,前一个,后一个,最后一个元素。同时前三个就是返回该集合的符合条件的子集合。

package Test01;

import java.util.TreeSet;

public class TestTreeSet {
     
  public static void main(String[] args) {
    TreeSet num =new TreeSet();
    num.add(2);
num.add(
-2); num.add(10); num.add(9); System.out.println(num); //看出:不是按照添加的顺序来,是数字由小到大排序 System.out.println(num.first()); //看出:数字由小到大排序的第一个 System.out.println("9到12 之间的"+num.subSet(9, 12)); System.out.println("比8小的"+num.headSet(8)); System.out.println("比8大的"+num.tailSet(8)); } }

与hashset采用hash算法决定元素的存储位置,TreeSet采用红黑树的数据结构(待跟进)来存储集合元素。那么他的排序规则是怎么的呢?

自然排序(默认情况)。

       调用TreeSet的无参的构造器,并实现Comparable接口,实现里的 compareTo(Object obj)方法,来比较集合元素的大小,然后按照compareTo里的排序。

     该种方法注意:

向TreeSet里添加元素时,只有第一个无须实现Comparable接口,后面的必须实现。(第二个及后面的会调用compareTo方法,与集合里的其他元素比较,要求了比较的两个元素都是一个类的实例,否则会ClassCastException)

package Test01;
import java.util.TreeSet;
 public class Foo implements Comparable{
    int num;
    public Foo(int num) {
        this.num =num;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "foo:"+this.getNum();
    }
    @Override
    public int compareTo(Object obj) {
        // TODO Auto-generated method stub
        if(obj instanceof Foo) {
             Foo f    =  (Foo) obj;
             if(this.num > f.getNum()) {
                 return 1;
             }
             if(this.num == f.getNum()) {
                 return 0;
             }
             else
                 return -1;
             
        }
        else return 0;
         
    }
    public static void main(String[] args) {
        TreeSet<Foo> test = new TreeSet<>();
        test.add(new Foo(8));        test.add(new Foo(3));
        System.out.println(test);
    }
     
} 

下面的一些常用的类已经实现了Comparable接口,提供了比较大小的标准:

BigDecimal

character

Boolean

String

Date Time

对于TreeSet集合来说,判断两个对象是否相等的唯一标准 是compareTo(Object obj)返回0,是0 就相等,不是0就不等。就不会让相等的对象进入集合。

举例

(正确的结果)能够插入两个compare 不等于0但是equals为true的对象

package Test01;

import java.util.Comparator;
import java.util.TreeSet;

public class Comp implements Comparator<Foo>{

    @Override
    public int compare(Foo o1, Foo o2) {
          return 1;
     }
    
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return true;
    }

    public  static void main(String[] args) {
        TreeSet<Foo> t = new TreeSet<>(new Comp());
        Foo f = new Foo(0);
        t.add(f);
        t.add(f);
        System.out.println(t);
        t.first().num =9;
        System.out.println(t);
        
    }
}

 留意下注释的差别,(问题已解决)

package Test01;

import java.util.TreeSet;

public class Test implements Comparable{
    int num;
    public Test(int num) {
        this.num=num;
    }
    public int getNum() {
    return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    @Override
    public boolean equals(Object obj) {
        // TODO Auto-generated method stub
        return true;
    }
    @Override
    public int compareTo(Object o) {
        // TODO Auto-generated method stub
        return 1;
    }
    public  static void main(String[] args) {
        TreeSet  t = new TreeSet();
        Test f = new Test(0);
        t.add(f);
       
        System.out.println("会把同一个对象但是compareTo返回1添加进TreeSet吗?"+ t.add(f));   //equals不是评价对象相等的标准,compareTo返回0才相等。返回true
        System.out.println(t);
        ((Test)(t.first())).num=9;   //修改第一个元素,下面一行发现最后一个元素也被改成了9
        
        System.out.println( ((Test)(t.last())).num);
    }

}
 

由正确的结果注意:TreeSet也是Set,equals结果注意保持和compareTo结果一致。因为如果compareTo 等于0,但是equals发现false,就和Set冲突。

和hashset同样,讨论下,可变对象插入删除问题(留意注释部分)

package Test01;

import java.util.Iterator;
import java.util.TreeSet;

class mutClass implements Comparable{
    public int count;
    public  mutClass(int count) {
        this.count =count;
    }
    public  boolean equals(Object obj) {
        if(this == obj) {
            return true;
        }
        if(obj != null && obj.getClass() == mutClass.class) {
            mutClass m =(mutClass) obj;
            return this.count == m.count;
        }
        return false;
    }
    public  int hashcode() {
        return this.count;
    }
    public String toString() {
        return "试试mutClass[count=" + count + "]";
    }
    @Override
    public int compareTo(Object o) {
        // TODO Auto-generated method stub
        mutClass m = (mutClass) o;
        return count>m.count?1 :count<m.count?-1 :0;
    }
    
}
public class TestTreeSet {
   @SuppressWarnings("unchecked")
public static void main(String[] args){
       TreeSet testHashSet =new TreeSet(); 
       mutClass a = new mutClass(3);
       mutClass b = new mutClass(1);
       mutClass c = new mutClass(-9);
       mutClass d = new mutClass(9);
       testHashSet.add(a);
       testHashSet.add(b);
       testHashSet.add(c);
       testHashSet.add(d);
        System.out.println("第一次"+testHashSet);
        ((mutClass)testHashSet.first()).count =20;
        System.out.println("第二次"+testHashSet);   //修改可变对象的实例变量,不会调整顺序
       ((mutClass)testHashSet.last()).count =1;   //修改可变对象的实例变量,不会调整顺序,且可能出现重复对象的情况
       System.out.println("第三次"+testHashSet);
       System.out.println(testHashSet.remove(new mutClass(1)));  //删除实例变量被修改的元素,应该删除失败,但是我删除成功了?
       System.out.println("第四次"+testHashSet);

    }
}

 定制排序。

自己写个比较器的类,传入TreeSet的有参数的构造器,这样往集合里add元素就能按照定制的顺序排序了。

package Test01;

import java.util.Comparator;
import java.util.TreeSet;

public class Comp implements Comparator<Foo>{

    @Override
    public int compare(Foo o1, Foo o2) {
        // TODO Auto-generated method stub
        if(o1.getNum()>o2.getNum()) {
            return 1;
        }
        if (o1.getNum() == o2.getNum()) {
            return 0;
        }
        else return -1;
     }
    public  static void main(String[] args) {
        TreeSet<Foo> t = new TreeSet<>(new Comp());
        t.add(new Foo(0));
        t.add(new Foo(-9));
        System.out.println(t);
    }
}
原文地址:https://www.cnblogs.com/yizhizhangBlog/p/9257892.html