zoukankan      html  css  js  c++  java
  • TreeSet集合为什么要实现Comparable?

    首先,让我们来看看JDK中TreeSet类的add方法

    /**
         * Adds the specified element to this set if it is not already present.
         * More formally, adds the specified element {@code e} to this set if
         * the set contains no element {@code e2} such that
         * <tt>(e==null ? e2==null : e.equals(e2))</tt>.
         * If this set already contains the element, the call leaves the set
         * unchanged and returns {@code false}.
         *
         * @param e element to be added to this set
         * @return {@code true} if this set did not already contain the specified
         *         element
         * @throws ClassCastException if the specified object cannot be compared
         *         with the elements currently in this set
         * @throws NullPointerException if the specified element is null
         *         and this set uses natural ordering, or its comparator
         *         does not permit null elements
         */
        public boolean add(E e) {
        return m.put(e, PRESENT)==null;
        }

    注意抛出的异常~~

    * @throws ClassCastException if the specified object cannot be compared with the elements currently in this set

    也就是说,如果添加的元素不能和已有元素做比较就抛出ClassCastException异常~
    那两个元素如果判断可比呢?
    有两种办法,其中一种就是实现 Comparable接口
    JDK中很多类都实现了Comparable接口,比如Integer
    至于TreeSet为什么要这样设计,是因为这个类需要实现元素排序的功能
    那如何实现的排序呢?
    我们来看 TreeSet的构造方法

     /**
         * Constructs a new, empty tree set, sorted according to the
         * natural ordering of its elements.  All elements inserted into
         * the set must implement the {@link Comparable} interface.
         * Furthermore, all such elements must be <i>mutually
         * comparable</i>: {@code e1.compareTo(e2)} must not throw a
         * {@code ClassCastException} for any elements {@code e1} and
         * {@code e2} in the set.  If the user attempts to add an element
         * to the set that violates this constraint (for example, the user
         * attempts to add a string element to a set whose elements are
         * integers), the {@code add} call will throw a
         * {@code ClassCastException}.
         */
        public TreeSet() {
        this(new TreeMap<E,Object>());
        }
     /**
         * Constructs a set backed by the specified navigable map.
         */
        TreeSet(NavigableMap<E,Object> m) {
            this.m = m;
        }

    你可以发现,排序功能实际上是由TreeMap实现的
    TreeSet的add方法实际上就是调用的的TreeMap的put方法~~
    最后~看看put方法的源码

    /**
         * Associates the specified value with the specified key in this map.
         * If the map previously contained a mapping for the key, the old
         * value is replaced.
         *
         * @param key key with which the specified value is to be associated
         * @param value value to be associated with the specified key
         *
         * @return the previous value associated with <tt>key</tt>, or
         *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
         *         (A <tt>null</tt> return can also indicate that the map
         *         previously associated <tt>null</tt> with <tt>key</tt>.)
         * @throws ClassCastException if the specified key cannot be compared
         *         with the keys currently in the map
         * @throws NullPointerException if the specified key is null
         *         and this map uses natural ordering, or its comparator
         *         does not permit null keys
         */
        public V put(K key, V value) {
            Entry<K,V> t = root;
            if (t == null) {
            // TBD:
            // 5045147: (coll) Adding null to an empty TreeSet should
            // throw NullPointerException
            //
            // compare(key, key); // type check
                root = new Entry<K,V>(key, value, null);
                size = 1;
                modCount++;
                return null;
            }
            int cmp;
            Entry<K,V> parent;
            // split comparator and comparable paths
            Comparator<? super K> cpr = comparator;
            if (cpr != 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();
                Comparable<? super K> k = (Comparable<? super K>) key;
                do {
                    parent = t;
                    cmp = k.compareTo(t.key);
                    if (cmp < 0)
                        t = t.left;
                    else if (cmp > 0)
                        t = t.right;
                    else
                        return t.setValue(value);
                } while (t != null);
            }
            Entry<K,V> e = new Entry<K,V>(key, value, parent);
            if (cmp < 0)
                parent.left = e;
            else
                parent.right = e;
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }

    你可以发现,这个二叉树排序中有一条这样的语句来判断大小

    cmp = k.compareTo(t.key);

    这里k,也就是我们TreeSet.add(k) 方法传入的参数

    Comparable<? super K> k = (Comparable<? super K>) key;

    可见,插入TreeSet的对象必须实现Compareble接口

  • 相关阅读:
    【Mysql sql inject】【入门篇】sqli-labs使用 part 3【15-17】
    【Mysql sql inject】【入门篇】SQLi-Labs使用 part 2【12-14】
    【Mysql sql inject】【入门篇】SQLi-Labs使用 part 1【01-11】
    【CTF WEB】ISCC 2016 web 2题记录
    【Mysql sql inject】POST方法BASE64编码注入write-up
    【sql server inject】使用动态查询执行sql语句实例
    【跨站关】网络信息安全攻防学习平台跨站过关的彩蛋
    【sql inject】sql盲注技巧
    【php】随缘php企业网站管理系统V2.0 shownews.php注入漏洞
    ASP.NET新建解决方案和网站
  • 原文地址:https://www.cnblogs.com/tinaluo/p/8362382.html
Copyright © 2011-2022 走看看