Maison  >  Article  >  Java  >  Amélioration Java (24) -----HashSet

Amélioration Java (24) -----HashSet

黄舟
黄舟original
2017-02-10 14:23:421152parcourir

Texte original de : http://www.php.cn/

Dans le billet de blog précédent ( Chapitre sur l'amélioration de Java (23) -----HashMap ) explique en détail le processus d'implémentation de HashMap. Pour HashSet, il est implémenté sur la base de HashMap et la couche inférieure utilise HashMap pour enregistrer les éléments. . Donc, si vous êtes familier avec HashMap, alors HashSet est si simple !!

Définition


public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

HashSet hérite de la classe AbstractSet et implémente les interfaces Set, Cloneable et Serialisable. Parmi eux, AbstractSet fournit l'implémentation principale de l'interface Set, minimisant ainsi le travail requis pour implémenter cette interface. L'interface Set est une collection qui ne contient pas d'éléments en double. Elle conserve son propre ordre interne, donc l'accès aléatoire n'a pas de sens.

Attributs de base


//基于HashMap实现,底层使用HashMap保存所有元素
private transient HashMap<E,Object> map;

 //定义一个Object对象作为HashMap的value
 private static final Object PRESENT = new Object();




/**
         * 默认构造函数
         * 初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。
         */
        public HashSet() {
            map = new HashMap<>();
        }
        
        /**
         * 构造一个包含指定 collection 中的元素的新 set。
         */
        public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
        
        /**
         * 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子
         */
        public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
           
        /**
         * 构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。
         */
        public HashSet(int initialCapacity) {
           map = new HashMap<>(initialCapacity);
        }
           
        /**
         * 在API中我没有看到这个构造函数,今天看源码才发现(原来访问权限为包权限,不对外公开的)
         * 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。
         * dummy 为标识 该构造函数主要作用是对LinkedHashSet起到一个支持作用
         */
        HashSet(int initialCapacity, float loadFactor, boolean dummy) {
           map = new LinkedHashMap<>(initialCapacity, loadFactor);
        }


HashSet peut être vu à partir du constructeur Toutes les constructions construisent un nouveau HashMap, et le dernier constructeur n'est pas public pour l'accès aux packages et ne prend effet que lors de l'utilisation de LinkedHashSet.

2. Méthode

Puisque HashSet est basé sur HashMap, alors pour HashSet, le processus de mise en œuvre de sa méthode est très simple. La méthode iterator() renvoie un itérateur qui parcourt les éléments de cet ensemble. L'ordre dans lequel les éléments sont renvoyés n'est pas précis. L'appel sous-jacent au keySet de HashMap renvoie toutes les clés. Cela reflète que tous les éléments du HashSet sont stockés dans la clé du HashMap et que la valeur est l'objet PRESENT utilisé, qui est final statique.

size() renvoie le nombre d'éléments dans cet ensemble (la capacité de l'ensemble ). La couche inférieure appelle la méthode size de HashMap et renvoie la taille du conteneur HashMap.

public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

isEmpty(), détermine si l'ensemble HashSet() est vide, renvoie s'il est vide

true, sinon false
public int size() {
        return map.size();
    }
est renvoyé.

public boolean isEmpty() {
        return map.isEmpty();
    }
contains(), détermine si un élément existe dans HashSet(), existe Renvoie vrai , sinon renvoie false. Pour être plus précis, cette relation doit être satisfaite pour renvoyer vrai : (o==null ? e==null : o.equals(e)). La couche inférieure appelle containKey pour déterminer si la valeur clé de HashMap est vide.

add() Si cet ensemble ne contient pas encore l'élément spécifié, ajoutez l'élément spécifié élément. Si cet ensemble ne contient pas e2 qui satisfait (e==null ? e2==null : e.equals(e2)), alors e2 est ajouté à l'ensemble, sinon il n'est pas ajouté et false est renvoyé. Puisque la couche inférieure utilise la méthode put de HashMap pour construire key = e, value = PRESENT dans une paire clé-valeur, lorsque e existe dans la clé de HashMap, la valeur écrasera la valeur d'origine, mais la clé reste inchangée, donc Si un élément e existant est ajouté au HashSet, l'élément nouvellement ajouté ne sera pas enregistré dans le HashMap, cela satisfait donc à la fonctionnalité selon laquelle les éléments du HashSet ne seront pas répétés.

public boolean contains(Object o) {
        return map.containsKey(o);
    }

                                                                                             

La couche inférieure utilise la méthode Remove de HashMap pour supprimer l'entrée spécifiée.
public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

public void clear() {
        map.clear();
    }

          clear从此 set 中移除所有元素。底层调用HashMap的clear方法清除所有的Entry。

public Object clone() {
        try {
            HashSet<E> newSet = (HashSet<E>) super.clone();
            newSet.map = (HashMap<E, Object>) map.clone();
            return newSet;
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }

          clone返回此 HashSet 实例的浅表副本:并没有复制这些元素本身。

          后记:

          由于HashSet底层使用了HashMap实现,使其的实现过程变得非常简单,如果你对HashMap比较了解,那么HashSet简直是小菜一碟。有两个方法对HashMap和HashSet而言是非常重要的,下篇将详细讲解hashcode和equals。

---------------------------------------------------------------------------------------------------------

以上就是java提高篇(二四)-----HashSet的内容,更多相关内容请关注PHP中文网(www.php.cn)!



Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn