TreeSet研究

 

TreeSet拥有和Set的基础属性:不能重复。

同时它还拥有一个隐藏排序功能。

 

public class RandomTest {

    public static void main(String[] args) {
        Random random = new Random();
        Set<Integer> set = new TreeSet<Integer>();

        while (set.size() != 6) {
            // 获取随机数
            int randomValue = random.nextInt(33) + 1;
            
            System.out.print(randomValue + " ");
            
            // 写入TreeSet集合
            set.add(randomValue);
        }
        System.out.println("\n------------");
        Iterator it = set.iterator();
        
        // 输出TreeSet内容
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
    }
}

 

 输出

 

 

15 4 23 4 9 19 8 
------------
4 8 9 15 19 23

 

 

 

在随机数放入TreeSet之后,再次输出时进行了排序。

看TreeSet的源码的add方法

 

public boolean add(E o) {
	return m.put(o, PRESENT)==null;
}

 

 再看m和PRESENT是什么

 

 

private transient SortedMap<E,Object> m; // The backing Map
private static final Object PRESENT = new Object();

 

 看m的初始化

 

public TreeSet() {
	this(new TreeMap<E,Object>());
}

 

 基本明白了,TreeSet是实际上使用了一个含排序功能的TreeMap存放的数据,key是Set集合中的元素,value是一个虚拟Object。

 

看TreeMap的put方法

 

    public V put(K key, V value) {
        Entry<K,V> t = root;

        if (t == null) {
            incrementSize();
            root = new Entry<K,V>(key, value, null);
            return null;
       }

        while (true) {
            int cmp = compare(key, t.key);
            if (cmp == 0) {
                return t.setValue(value);
            } else if (cmp < 0) {
                if (t.left != null) {
                    t = t.left;
                } else {
                    incrementSize();
                    t.left = new Entry<K,V>(key, value, t);
                    fixAfterInsertion(t.left);
                    return null;
                }
            } else { // cmp > 0
                if (t.right != null) {
                    t = t.right;
                } else {
                    incrementSize();
                    t.right = new Entry<K,V>(key, value, t);
                    fixAfterInsertion(t.right);
                    return null;
                }
            }
        }
    }

 它进行了排序,但排序的关键是compare方法,该方法制定和TreeMap的key值顺序,也就是TreeSet的元素顺序

    private Comparator<? super K> comparator = null;

    private int compare(K k1, K k2) {
        return (comparator==null ? ((Comparable</*-*/K>)k1).compareTo(k2)
                                 : comparator.compare((K)k1, (K)k2));
    }

 如果我们想要修改TreeSet的排序,那么需要重写TreeMap的compare方法,即自定义comparator,其实TreeMap和TreeSet已经提供了入口

    public TreeSet(Comparator<? super E> c) {
		this(new TreeMap<E,Object>(c));
    }
    public TreeMap(Comparator<? super K> c) {
        this.comparator = c;
    }

 修改一下之前的代码,我们自定义Comparator,让TreeSet的元素倒序输出

public class RandomTest {

    public static void main(String[] args) {
        Random random = new Random();
        // 自定义的Comparater
        MyComparater comparater = new MyComparater();
        
        // 使用指定的构造方法
        Set<Integer> set = new TreeSet<Integer>(comparater);

        while (set.size() != 6) {
            // 获取随机数
            int randomValue = random.nextInt(33) + 1;
            
            System.out.print(randomValue + " ");
            
            // 写入TreeSet集合
            set.add(randomValue);
        }
        System.out.println("\n------------");
        Iterator it = set.iterator();
        
        // 输出TreeSet内容
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
    }
}


class MyComparater implements Comparator<Integer>{

    public int compare(Integer o1, Integer o2) {
        int val1 =  o1.intValue();
        int val2 =  o2.intValue();
        return (val1 > val2 ? -1 : (val1 == val2 ? 0 : 1));
    }

}

输出:

3 16 16 25 5 3 21 11 
------------
25 21 16 11 5 3

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值