Table de hachage et propriétés

Continuez à créer, accélérez la croissance ! C'est le 5ème jour de ma participation au "Nuggets Daily New Plan · June Update Challenge", cliquez pour voir les détails de l'événement .

Cet article en apprend sur HashTable, qui est une ancienne classe qui est fondamentalement abolie, mais l'apprendre aide à comprendre HashMap.

Introduction à HashTable

HashTable est un type de données de paires clé-valeur clé-valeur, qui est relativement ancien et a été fondamentalement aboli et n'est plus utilisé. L'utilisation de la synchronisation pour assurer la synchronisation a une faible efficacité. Généralement, un thread unique est converti pour utiliser HashMap, et multi- le threading utilise ConcurrentHashMap.

Mais apprendre comment il est implémenté aide à comprendre l'implémentation de hashMap.

Relation d'héritage HashTable

Héritez de la classe Dictionary et implémentez l'interface Map.

image-20220520003443203.png

Principe de la table de hachage

Le principe de hashTable est à peu près le même que celui de hashMap. Dans certains aspects de l'algorithme et de la conception, hashTable est inférieur à hashMap.

Propriété HashTableHashTable property

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

Élément d'insertion HashTable

  • Lorsque la valeur de la clé est répétée, écrasez et renvoyez l'ancienne valeur
  • Lorsque la valeur de la clé n'est pas répétée, insérez-la directement. S'il y a un conflit, la fermeture éclair est envoyée pour résoudre

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

L'opération de reste est utilisée pour obtenir l'index de hachage, ce qui est très inefficace par rapport à l'opération à un bit de hashMap.

L'astuce ici est d'effectuer une opération ET avec 0x7FFFFFFF pour éviter l'apparition de nombres négatifs

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;
}
复制代码

méthode addEntryaddEntry method

Si le nombre de nœuds dépasse la valeur critique, la capacité sera étendue.

Sinon, insérez l'élément directement, ou la méthode zipper résoudra le conflit

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++;
}
复制代码

méthode rehash()

La méthode d'expansion ici hache simplement les nœuds dans un nouveau tableau et ne raccourcit pas la liste chaînée.

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;
        }
    }
}
复制代码

Icône de résolution de conflit de cheveux avec fermeture éclair :

image-20220520023906652.png


Introduction aux propriétés

Les propriétés héritent de Hashtable et peuvent être utilisées comme carte. Il étend certaines méthodes en interne et permet uniquement d'ajouter une valeur-clé String, mais elles sont toutes implémentées en fonction de hashTable. Il est le plus utilisé comme classe d'outil de configuration.

utilisation

les propriétés sont utilisées comme carte

/**
 * properties作为map使用
 */
@Test
public 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"));
}
复制代码

Sa méthode d'extension ne peut ajouter que la clé-valeur de la chaîne

@Test
public void useAsProp() {
    Properties prop = new Properties();
    prop.setProperty("name","name");
    prop.setProperty("age","23");
    prop.setProperty("email","[email protected]");
    System.out.println(prop);
    prop.forEach((key, value) -> {
        System.out.println("{key" + key + "," + "value" + value + "}");
    });
}
复制代码

Certaines classes ont leurs propres propriétés

/**
 * 也可以自己写一个配置类
 */
@Test
public 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 = "[email protected]";
        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;
    }
复制代码

Afin d'éviter un certain codage en dur, les informations de configuration peuvent être configurées sous la forme d'un fichier de configuration, qui est généralement utilisé pour les liens de base de données ou certaines informations de classe de configuration.

propriétés.utilisateur :

name=yyc
age=23
hobby=ball
复制代码
@Test
public void readProp() throws IOException {

    InputStream in = PropertiesTest.class.getClassLoader().getResourceAsStream("user.properties");
    Properties prop = new Properties();
    prop.load(in);
    String name = prop.getProperty("name");
    String age = prop.getProperty("age");
    String hobby = prop.getProperty("hobby");
    System.out.println("{name:" + name + "," + "age:" + age + "," + "hobby" + hobby + "}");
}
复制代码

Vous pouvez également sortir les propriétés sous forme de fichier


/**
 * 也可以输出为properties  或  xml
 * @throws IOException
 */
@Test
public void writeProp() throws IOException {

    //创建配置
    Properties prop = new Properties();
    prop.setProperty("name","name");
    prop.setProperty("age","23");
    prop.setProperty("email","[email protected]");
    System.out.println(prop);
    prop.forEach((key, value) -> {
        System.out.println("{key" + key + "," + "value" + value + "}");
    });
    //创建  outputStream
    FileWriter fileWriter = new FileWriter(new File("D:\\user.properties"));
    //写入文件
    prop.store(fileWriter,"user信息");

}
复制代码

image-20220521005020873.png

Je suppose que tu aimes

Origine juejin.im/post/7103534218403135525
conseillé
Classement