【Java集合】TreeMap

概述

        TreeMap实现了SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序, 也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。 如果需要一个按键排序的map,建议使用TreeMap。 在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的 Comparator,否则会抛java.lang.ClassCastException 类型的异常。

数据结构

        TreeMap底层是基于红黑树实现的,红黑树是一种自平衡的二叉查找树,对插入的元素按顺序存储,红黑树在最坏的情况下也能保持良好的性能,查找、插入和删除操作的时间复杂度均为 O(logn)。想了解红黑树的可通过可视化网站先了解一下:红黑树可视化

构造方法

无参构造方法:

public TreeMap() {
    this.comparator = null;
}

可自定义排序规则的构造方法,TreeMap默认是按升序排序的,在构造方法中传入Comparator.reverseOrder()可以使TreeMap按降序排序。

public TreeMap(Comparator<? super K> var1) {
    this.comparator = var1;
}

带有Map参数的构造方法,可将如HashMap之类的Map集合元素插入TreeMap进行排序:

public TreeMap(Map<? extends K, ? extends V> var1) {
    this.comparator = null;
    this.putAll(var1);
}

基本方法

添加元素put(),向红黑树中添加一个节点,可能会破坏红黑树的平衡性,fixAfterInsertion()方法可以对添加节点后的红黑树进行重平衡操作。

public V put(K var1, V var2) {
    TreeMap.Entry var3 = this.root;
    if (var3 == null) {
        this.compare(var1, var1);
        this.root = new TreeMap.Entry(var1, var2, (TreeMap.Entry)null);
        this.size = 1;
        ++this.modCount;
        return null;
    } else {
        Comparator var6 = this.comparator;
        int var4;
        TreeMap.Entry var5;
        if (var6 != null) {
            do {
                var5 = var3;
                var4 = var6.compare(var1, var3.key);
                if (var4 < 0) {
                    var3 = var3.left;
                } else {
                    if (var4 <= 0) {
                        return var3.setValue(var2);
                    }

                    var3 = var3.right;
                }
            } while(var3 != null);
        } else {
            if (var1 == null) {
                throw new NullPointerException();
            }

            Comparable var7 = (Comparable)var1;

            do {
                var5 = var3;
                var4 = var7.compareTo(var3.key);
                if (var4 < 0) {
                    var3 = var3.left;
                } else {
                    if (var4 <= 0) {
                        return var3.setValue(var2);
                    }

                    var3 = var3.right;
                }
            } while(var3 != null);
        }

        TreeMap.Entry var8 = new TreeMap.Entry(var1, var2, var5);
        if (var4 < 0) {
            var5.left = var8;
        } else {
            var5.right = var8;
        }

        this.fixAfterInsertion(var8);//重平衡
        ++this.size;
        ++this.modCount;
        return null;
    }
}

查找元素get(),红黑树的查找和普通二叉树的查找并没有什么区别。

public V get(Object var1) {
    TreeMap.Entry var2 = this.getEntry(var1);
    return var2 == null ? null : var2.value;
}

final TreeMap.Entry<K, V> getEntry(Object var1) {
        if (this.comparator != null) {
            return this.getEntryUsingComparator(var1);
        } else if (var1 == null) {
            throw new NullPointerException();
        } else {
            Comparable var2 = (Comparable)var1;
            TreeMap.Entry var3 = this.root;

            while(var3 != null) {
                int var4 = var2.compareTo(var3.key);
                if (var4 < 0) {
                    var3 = var3.left;
                } else {
                    if (var4 <= 0) {
                        return var3;
                    }

                    var3 = var3.right;
                }
            }

            return null;
        }
    }

删除元素remove(),从红黑树中删除一个节点,也可能会破坏红黑树的平衡性,fixAfterDeletion()方法可以对删除节点后的红黑树进行重平衡操作。

public V remove(Object var1) {
    TreeMap.Entry var2 = this.getEntry(var1);
    if (var2 == null) {
        return null;
    } else {
        Object var3 = var2.value;
        this.deleteEntry(var2);
        return var3;
    }
}

private void deleteEntry(TreeMap.Entry<K, V> var1) {
        ++this.modCount;
        --this.size;
        TreeMap.Entry var2;
        if (var1.left != null && var1.right != null) {
            var2 = successor(var1);
            var1.key = var2.key;
            var1.value = var2.value;
            var1 = var2;
        }

        var2 = var1.left != null ? var1.left : var1.right;
        if (var2 != null) {
            var2.parent = var1.parent;
            if (var1.parent == null) {
                this.root = var2;
            } else if (var1 == var1.parent.left) {
                var1.parent.left = var2;
            } else {
                var1.parent.right = var2;
            }

            var1.left = var1.right = var1.parent = null;
            if (var1.color) {
                this.fixAfterDeletion(var2);
            }
        } else if (var1.parent == null) {
            this.root = null;
        } else {
            if (var1.color) {
                this.fixAfterDeletion(var1);
            }

            if (var1.parent != null) {
                if (var1 == var1.parent.left) {
                    var1.parent.left = null;
                } else if (var1 == var1.parent.right) {
                    var1.parent.right = null;
                }

                var1.parent = null;
            }
        }

    }

适用场景

TreeMap是一种有序的映射,它可以在保证高效性的同时,提供一些基于排序的操作。因此,TreeMap适用于以下场景:

  • 需要按照键的自然顺序或者指定的比较器进行排序的场景,例如字典,排行榜,日程安排等。
  • 需要快速找到映射中最小或者最大的键或者值的场景,例如优先队列,堆,区间查询等。
  • 需要快速找到映射中某个范围内的所有键或者值的场景,例如范围搜索,前缀匹配,区间统计等。

参考

https://www.cnblogs.com/shoshana-kong/p/17548762.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值