本文共 1379 字,大约阅读时间需要 4 分钟。
转自:
前段时间工作中用到TreeMap集合,好久没用过以至于忘了会get到null值,现在把这个Mark一下。
问题描述:本来TreeMap是用来**去重**并排序的。当我们因为需要**强制其存储重复键值**的时候,通过get去获取对应的值就会发生错误,取出null值。
以下简单写一个Demo:Map<Integer, String> map = new TreeMap<>(new Comparator<Integer>() {
public int compare(Integer i1, Integer i2) {
// TODO Auto-generated method stub int num = i1 - i2; return num == 0 ? 1 : num; } });map.put(1, "一");
map.put(2, "二"); map.put(3, "三"); map.put(1, "四");System.out.println(map.get(1));
以上会get到null值,究其原因,可以从get方法源码中找到答案。TreeMap集合中实现Map集合的get代码如下:
public V get(Object key) {
Entry<K,V> p = getEntry(key); return (p==null ? null : p.value); }
再继续往下看 getEntry(key)方法:
final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance if (comparator != null) return getEntryUsingComparator(key); //以下代码省略
这个时候就已经很明显了,他用到了我们传入的比较器!!!
接着往下看getEntryUsingComparator(key);final Entry<K,V> getEntryUsingComparator(Object key) {
@SuppressWarnings("unchecked") K k = (K) key; Comparator<? super K> cpr = comparator; if (cpr != null) { Entry<K,V> p = root; while (p != null) { int cmp = cpr.compare(k, p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } } return null; }这个就很明白了,底层在往出取值的时候用到了我们传入的比较器中的compare()方法,TreeMap是二叉树结构存储数据。当我们拿着键去get值时,底层拿着我们传入的键去逐个比对此处调用比较器中的compare方法:小于零则往左边去找,大于零往右去找,只有当等于0时才返回该值,而我们强制compare()方法等于0的时候返回1,所以一直往右边去找,永远找不到,直到最后返回null
转载地址:http://tvhbn.baihongyu.com/