TreeMap的实现原理

TreeMap的原理(jdk1.7)

TreeMap的底层实现基于二叉树的红黑树,插入的值是按一定顺序排序的。

TreeMap的构造方法

TreeMap有四个构造方法

    1
    public TreeMap() {
        comparator = null;
    }
    创键空的TreeMap,采用自然排序
    
    2
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
    创建一个空的TreeMap,排序是根据comparator排序的,
    
    3
    public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        putAll(m);
    }
    创建一个新的TreeMap,m集合的值全部复制到TreeMap上,排序是用自然排序。运行时间的在n*log(n)时间内运行。
    
    4
    public TreeMap(SortedMap<K, ? extends V> m) {
        comparator = m.comparator();
        try {
            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }
    }
    创建一个新的TreeMap,并键m的值全部复制到TreeMap上,排序用的是m中指定的排序。这个方法运行时间是在线性时间内。

TreeMap的put()方法

public V put(K key, V value) {
        Entry<K,V> t = root;
        /*如果此时的红黑树为null,即这是插入的第一个节点,直接设置为根节点*/
        if (t == null) {
            /*类型检查,不能为null*/
            compare(key, key); 

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        Entry<K,V> parent;
        
        Comparator<? super K> cpr = comparator;
/*判断该TreeMap在创建时是否制定了Comparator,若是,排序使用Comparatr中的compare()方法,没有则使用默认的Comparable的自然排序*/
        if (cpr != null) {
            /*循环红黑书,能匹配到key就替换value*/
            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<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
//添加完节点,开始维护红黑树
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

因为是根据key排序的,所以要求TreeMap中的key数据类型要一致,不然会报ClassCastException。

Comparable("自然排序")

在java中,有一个接口类Comparable。该类有一个方法compareTo(T o)。所有的封装基本类型都实现了该接口并重写了这个方法。compareTo()就是我们常说的自然排序。注意:key不能为null,因为会调用key.compareTo()方法。

例子:

Map treeMap = new TreeMap();

Comparator(比较器)

TreeMap中使用的比较器。若我们不想用自然排序设计的比较规则,想自己设计一套规则,则需要创建该接口的示例,并实现compare()方法,在创建TreeMap时通过构造方法传入。注意:key可以为null,如果你想限制你可以在Comparator的compare()方法里面去限制。

例子:

Comparator comparator = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1.toString().length()>o2.toString().length()){
                    return 1;
                }else{
                    return -1;
                }
            }
        };
        Map treeMap = new TreeMap(comparator);

TreeMap的get()方法

public V get(Object key) {
        Entry<K,V> p = getEntry(key);
        return (p==null ? null : p.value);
}

final Entry<K,V> getEntry(Object key) {
        // 区别是自然排序还是Comparator排序
        if (comparator != null)
            return getEntryUsingComparator(key);
        if (key == null)
            throw new NullPointerException();
        Comparable<? super K> k = (Comparable<? super K>) key;
        Entry<K,V> p = root;
        while (p != null) {
            int cmp = k.compareTo(p.key);
            if (cmp < 0)
                p = p.left;
            else if (cmp > 0)
                p = p.right;
            else
                return p;
        }
        return null;
    }

TreeMap的get()倒是没什么奇特之处,只是要区别是自然排序和Comparator排序,根据不同的排序调用不同的比较方法去定位想要的数据。因为底层是红黑树,所以检索的速度相当快,时间复杂度为O(log(n))。

例子

用默认自然排序:

        Map treeMap = new TreeMap();
        treeMap.put("1","1");
        treeMap.put("2","2");
        treeMap.put("7","7");
        treeMap.put("3","3");
        treeMap.put("8","8");
        treeMap.put("4","4");
        treeMap.put("5","5");
        Set keySet = treeMap.keySet();
        Iterator keyItr = keySet.iterator();
        while(keyItr.hasNext()){
            String key = (String)keyItr.next();
            String value = (String)treeMap.get(key);
            System.out.println(value);
        }
	输出结果:
		1
		2
		3
		4
		5
		7
		8

使用比较器comparator

        public void comparatorTest(){
			class DemoComparator implements Comparator<String>{
				@Override
				public int compare(String o1, String o2) {
					if(o1.length()==o2.length() && o1.equals(o2)){
						return 0;
					}else if(o1.length()<o2.length()){
						return 1;
					}else{
						return -1;
					}
				}
			}
			Map treeMap = new TreeMap(new DemoComparator());
			treeMap.put("111","1");
			treeMap.put("2","2");
			treeMap.put("71","7");
			treeMap.put("31111","3");
			treeMap.put("8111","8");
			treeMap.put("4111111","4");
			treeMap.put("511111","5");
			Set keySet = treeMap.keySet();
			Iterator keyItr = keySet.iterator();
			while(keyItr.hasNext()){
				String key = (String)keyItr.next();
				System.out.println("key:"+key);
				String value = (String)treeMap.get(key);
				System.out.println("value:"+value);
			}
		}
		结果:
			key:4111111,value:4
			key:511111,value:5
			key:31111,value:3
			key:8111,value:8
			key:111,value:1
			key:71,value:7
			key:2,value:2
		简单的设计一个根据key字符串长度来排序的比较器。

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_32844875/article/details/82727138