首页>>后端>>java->HashTable&Properties

HashTable&Properties

时间:2023-12-07 本站 点击:0

本文学习HashTable,这是一个古老类,基本上被废除,但是学习它有助于理解HashMap。

HashTable简介

HashTable是一个key-value键值对的数据类型,较为古老,现已基本废除不再使用,使用synchronized保证同步,效率较低,一般单线程转为使用HashMap,多线程使用ConcurrentHashMap。

但学习其实现方式有助于理解hashMap的实现。

HashTable继承关系

继承Dictionary类,实现Map接口。

HashTable原理

hashTable的原理和hashMap大致相同。在一些算法和设计方面,hashTable比hashMap低下。

HashTable属性

//节点数组private transient Entry<?,?>[] table;//节点个数private transient int count;//临界值private int threshold;//加载因子  0.75private float loadFactor;//模数,hashTable被修改的次数private transient int modCount = 0;

HashTable插入元素

当key值重复,就覆盖并返回旧的value

当key值不重复,直接插入。如果出现冲突,拉链发解决

一、(hash & 0x7FFFFFFF) % tab.length;

取余操作,获取散列下标,相比于hashMap的一次位运算,这里效率很低。

这里巧妙在于,与0x7FFFFFFF进行与运算,避免负数的出现

public synchronized V put(K key, V value) {    // Make sure the value is not null    //不允许插入null值    if (value == null) {        throw new NullPointerException();    }    // Makes sure the key is not already in the hashtable.    Entry<?,?> tab[] = table;    //这里并没有对key进行为空检测,是不合理的    int hash = key.hashCode();    //hash值与0x7FFFFFFF按位与,防止出现负数。    //与tab.length做取余操作,得到散列下标    int index = (hash & 0x7FFFFFFF) % tab.length;    @SuppressWarnings("unchecked")    Entry<K,V> entry = (Entry<K,V>)tab[index];    //不为空    for(; entry != null ; entry = entry.next) {        //出现重复则覆盖        if ((entry.hash == hash) && entry.key.equals(key)) {            V old = entry.value;            entry.value = value;            return old;        }    }    //出现冲突、或对应下标节点为空,插入元素    addEntry(hash, key, value, index);    return null;}

addEntry方法

如果节点个数超过临界值,就扩容。

否则直接插入元素,或拉链法解决冲突

private void addEntry(int hash, K key, V value, int index) {    modCount++;    Entry<?,?> tab[] = table;    if (count >= threshold) {        // Rehash the table if the threshold is exceeded        rehash();        tab = table;        hash = key.hashCode();        index = (hash & 0x7FFFFFFF) % tab.length;    }    // Creates the new entry.    @SuppressWarnings("unchecked")    Entry<K,V> e = (Entry<K,V>) tab[index];    tab[index] = new Entry<>(hash, key, value, e);    count++;}

rehash()方法

这里的扩容方法,只是简单的将节点散列到新的数组上,并没有做将链表变短的操作。

protected void rehash() {    int oldCapacity = table.length;    Entry<?,?>[] oldMap = table;    // overflow-conscious code    int newCapacity = (oldCapacity << 1) + 1;    if (newCapacity - MAX_ARRAY_SIZE > 0) {        if (oldCapacity == MAX_ARRAY_SIZE)            // Keep running with MAX_ARRAY_SIZE buckets            return;        newCapacity = MAX_ARRAY_SIZE;    }    Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];    modCount++;    threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);    table = newMap;    for (int i = oldCapacity ; i-- > 0 ;) {        //i下标对单向链表        for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {            Entry<K,V> e = old;            old = old.next;            //获取节点新下标            int index = (e.hash & 0x7FFFFFFF) % newCapacity;            //链接起来            e.next = (Entry<K,V>)newMap[index];            newMap[index] = e;        }    }}

拉链发解决冲突图示:

Properties简介

Properties 继承于 Hashtable,可以作为一个map使用。其内部扩展了一些方法,只允许添加String的key-value,不过都是基于hashTable实现的。其使用最多的是作为配置工具类使用。

使用

properties作为map使用

/** * properties作为map使用 */@Testpublic void propertiesUseAsMap() {    Properties prop = new Properties();    prop.put(1, "a");    prop.put(2, 2);    prop.put("3", new Object());    System.out.println(prop.get(1));    System.out.println(prop.get(2));    System.out.println(prop.get("3"));}

其扩展方法,只能添加字符串的key-valu

@Testpublic void useAsProp() {Properties prop = new Properties();prop.setProperty("name","name");prop.setProperty("age","23");prop.setProperty("email","123@qq.com");System.out.println(prop);prop.forEach((key, value) -> {System.out.println("{key" + key + "," + "value" + value + "}");});}

有一些类自带properties属性

/*** 也可以自己写一个配置类*/@Testpublic void testMyCP() {Properties prop = MyPropClass.getProperties();
System.out.println(prop);prop.forEach((key, value) -> {    System.out.println("{key" + key + "," + "value" + value + "}");});

}

class MyPropClass { private static Properties props; private static final String name; private static final String age; private static final String email;

static {    props = new Properties();    name = "yyc";    age = "23";    email = "123@qq.com";    initProperties();}private static void initProperties() {    props.setProperty("name", name);    props.setProperty("age", age);    props.setProperty("email", email);}public void setProperties(String key, String value) {    props.setProperty(key, value);}public String getProperties(String key) {    return props.getProperty(key);}public void setProperties(Properties properties) {    MyPropClass.props = properties;}public static Properties getProperties() {    return props;}

> 为了防止一些硬编码,可以使用配置文件的形式配置信息,一般用于数据库链接或一些配置的类信息。user.properties:```propertiesname=yycage=23hobby=ball

public synchronized V put(K key, V value) {    // Make sure the value is not null    //不允许插入null值    if (value == null) {        throw new NullPointerException();    }    // Makes sure the key is not already in the hashtable.    Entry<?,?> tab[] = table;    //这里并没有对key进行为空检测,是不合理的    int hash = key.hashCode();    //hash值与0x7FFFFFFF按位与,防止出现负数。    //与tab.length做取余操作,得到散列下标    int index = (hash & 0x7FFFFFFF) % tab.length;    @SuppressWarnings("unchecked")    Entry<K,V> entry = (Entry<K,V>)tab[index];    //不为空    for(; entry != null ; entry = entry.next) {        //出现重复则覆盖        if ((entry.hash == hash) && entry.key.equals(key)) {            V old = entry.value;            entry.value = value;            return old;        }    }    //出现冲突、或对应下标节点为空,插入元素    addEntry(hash, key, value, index);    return null;}0

同时也可以将Properties作为文件输出

public synchronized V put(K key, V value) {    // Make sure the value is not null    //不允许插入null值    if (value == null) {        throw new NullPointerException();    }    // Makes sure the key is not already in the hashtable.    Entry<?,?> tab[] = table;    //这里并没有对key进行为空检测,是不合理的    int hash = key.hashCode();    //hash值与0x7FFFFFFF按位与,防止出现负数。    //与tab.length做取余操作,得到散列下标    int index = (hash & 0x7FFFFFFF) % tab.length;    @SuppressWarnings("unchecked")    Entry<K,V> entry = (Entry<K,V>)tab[index];    //不为空    for(; entry != null ; entry = entry.next) {        //出现重复则覆盖        if ((entry.hash == hash) && entry.key.equals(key)) {            V old = entry.value;            entry.value = value;            return old;        }    }    //出现冲突、或对应下标节点为空,插入元素    addEntry(hash, key, value, index);    return null;}1

原文:https://juejin.cn/post/7103534218403135525


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/18676.html