Java继承 - TreeMap中的floorKey()和ceilingKey()的简单介绍及使用实例

本文介绍了Java TreeMap中的floorKey()和ceilingKey()方法,这两个方法源自NavigableMap接口。文章通过源码分析和实例演示,阐述了它们在实际应用中的使用场景,强调在声明时应使用NavigableMap,因为直接使用TreeMap可能无法调用这两个方法,同时提醒注意TreeMap的特性:key升序、key唯一。

TreeMap中的floorKey()和ceilingKey()

1. 介绍

我们先看一看TreeMap类,实现了众多接口,它的这两个方法来自NavigableMap类:

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable {...}

先看一看NavigableMap类中的floorKey()和ceilingKey()的API:

类型方法描述
KceilingKey(K key)返回大于或等于给定键的最小键,如果没有这样的键,则null
KfloorKey(K key)返回小于或等于给定键的最大键,如果没有这样的键,则null

而TreeMap中的这两个方法描述也是一样的,具体看一下源码,floorKey:

//floorKey(K key)
public K floorKey(K key) {
    return keyOrNull(getFloorEntry(key));
}
//getFloorEntry(K key)
final Entry<K,V> getFloorEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp > 0) {
            if (p.right != null)
                p = p.right;
            else
                return p;
        } else if (cmp < 0) {
            if (p.left != null) {
                p = p.left;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.left) {//获取到键中符合规定的最大键
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        } else
            return p;
    }
    return null;
}

ceilingKey:

public K ceilingKey(K key) {
    return keyOrNull(getCeilingEntry(key));
}
final Entry<K,V> getCeilingEntry(K key) {
    Entry<K,V> p = root;
    while (p != null) {
        int cmp = compare(key, p.key);
        if (cmp < 0) {
            if (p.left != null)
                p = p.left;
            else
                return p;
        } else if (cmp > 0) {
            if (p.right != null) {
                p = p.right;
            } else {
                Entry<K,V> parent = p.parent;
                Entry<K,V> ch = p;
                while (parent != null && ch == parent.right) {//获取到键中符合规定的最小键
                    ch = parent;
                    parent = parent.parent;
                }
                return parent;
            }
        } else
            return p;
    }
    return null;
}

示例:

public class Main {
    public static void main(String[] args) {
        Main m = new Main();
        TreeMap<Integer,String> map = new TreeMap<>();
        for (int i = 0; i < 10; i++)
            map.put(2*i,"value"+i);
        /**map:
         *   key: 0 1 2 3 4 5 6 7 8 9
         * value:...
         */
        map.floorKey(3);// 2
        map.ceilingKey(3);// 4
    }
}

在很多的需求中都能够使用到这一个方法。具体的需要注意的点就是这两个方法来之NavigableMap,在声明的时候最好使用TreeMap map = new TreeMap(),使用Map map = new TreeMap()是无法调用这两个方法的(这里涉及到向下转型的问题)。且TreeMap不保留存储顺序(内部以key升序)、key唯一等性质。

2. 实战使用

感兴趣的小伙伴可以看一看,挺有意思的…

https://ac.nowcoder.com/acm/contest/12949/E

import java.util.*;
public class Main {
    private static TreeMap<Integer,Integer> map = new TreeMap<>();
    private static int min = Integer.MAX_VALUE;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int s = sc.nextInt();
        int t = sc.nextInt();
        int count = 1,step = 1,index = 1;
        map.put(index,count);
        while(index > -20000 && index < 20000){//准备数据
            step *= -2;
            index += step;
            count++;
            map.put(index,count);
        }
        jump(s,t,0);
        System.out.print(min);
    }
    public static void jump(int s,int t,int count){//这一个count步数上一个count
        if(s == t){
            min = Math.min(min,count);
            return;
        }
        if(count > min) return;//越过就结束,继续增加没有意义
        if(count != 0) count++;
        Integer floor = map.floorKey(t - s);
        Integer ceil = map.ceilingKey(t - s);
        jump(s + floor,t,count + map.get(floor));
        if(ceil != null) jump(s + ceil,t,count + map.get(ceil));
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值