Java笔记整理 —— HashTable、TreeSet(TreeMap)

HashTable

扩容

底层有数组 Hashtable$Entry[],初始化大小为 11。临界值 threshold 为8 = 11 * 0.75。

调用put方法里的 addEntry(hash, key, value, index);  当满足 if (count >= threshold)  扩容(rehash)

int newCapacity = (oldCapacity << 1) + 1; //新容量计算方法
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
 // 临界值计算方法

Properties

Java 读写Properties配置文件 - 旭东的博客 - 博客园  感兴趣可以看这篇文章。

注意事项

1. Properties 继承 Hashtable,是无序的。

2. 可以通过 k-v 存放数据,当然key和value不能为null。

3. 常用方法:增 put(key,value),删 remove(key),改 put(相同的key,value),查 get(key)。

开发中如何选择集合实现类

一组对象指的就是只有key,没有value。 

TreeSet

构造方法

正常的TreeSet声明应该是这样的:

    TreeSet a = new TreeSet();

 但是TreeSet有一个构造器,可以传入一个比较器Comparator(匿名内部类)

    public static void main(String[] args) {
        TreeSet a = new TreeSet(new Comparator() { //匿名内部类
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).compareTo((String)o2); //按照字符串大小比较
            }
        });
        a.add("jack");
        a.add("a");
        a.add("sss");
        a.add("mmm");
        System.out.println(a);// [a, jack, mmm, sss]
    }

 要注意一个问题:假设要求按照字符串的length来从小到大排序

    public static void main(String[] args) {
        TreeSet a = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return ((String)o1).length() - ((String)o2).length(); //从小到大
            }
        });
        a.add("jack");
        a.add("a");
        a.add("sss");
        a.add("mmm");
        System.out.println(a); // [a, sss, jack]
    }

  可以发现 "mmm" 并没有加入进去,那么我们就需要追一下源码了。

        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        } // 初始化,生成一个新结点
        int cmp;
        Entry<K,V> parent;
        Comparator<? super K> cpr = comparator; //重点在这里,把比较器赋过去
        if (cpr != null) {
            do {   //对整个链表(key)进行循环,给当前key找适当位置
                parent = t;
                cmp = cpr.compare(key, t.key); //比较原结点与要加入的结点的key
                                               //这里会动态绑定到匿名内部类对象
                if (cmp < 0) 
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;  //按照比较结果移动指针
                else  //遍历过程中发现准备添加的key和当前已有的key相等
                    return t.setValue(value); //由于Set的value为PRESENT,因此相当于没加
            } while (t != null); //循环结束后,t就指向结点应该加入的位置
                                 //parent为上一次,因此结束后还需要再移动一次
        }
        ... //没有比较器的情况
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e; //按照比较结果把结点e放在正确位置(parent是原来的t)
        fixAfterInsertion(e);
        size++; //结点个数加一
        modCount++; //修改次数加一
        return null;
    }

   "sss" 是先加入的,长度为3。因为自定义的比较器是比较长度的,而 "mmm" 的长度也为3,因此结果为0,直接不加入了(参考do里面的else情况)。

   由于TreeSet的底层是TreeMap,因此比较器初始化方法在TreeMap里。

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

 TreeSet和TreeMap的底层都是TreeMap,因此TreeMap的源码不再做解析。

关于TreeSet加入自定义类 

    如果TreeSet没有重写Comparator,并且加入的类也没有实现Comparable接口,那么就会报错,因为add源码里需要赋予一个比较器。

        TreeSet a = new TreeSet();
        a.add(1); //这样是没有问题的,因为1相当于Integer,而Integer实现了Comparable接口
public static void main(String[] args){
    TreeSet a = new TreeSet();
    a.add(new Car("AAA",2331313)); //报错 ClassCastException
}

class Car{
    String name;
    double price;

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }
}
        TreeSet a = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        }); //这样写就没问题了

class Car implements Comparable{ //这样写也没问题,Car类实现了Comparable接口
    String name;
    double price;

    public Car(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override  //重写compareTo方法
    public int compareTo(Object o) {
        return 0;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值