Maison  >  Article  >  Java  >  Introduction détaillée à un résumé complet des connaissances liées aux conteneurs Java (image)

Introduction détaillée à un résumé complet des connaissances liées aux conteneurs Java (image)

黄舟
黄舟original
2017-03-22 11:04:461454parcourir

Java UtilityClass Library fournit un ensemble assez complet de conteneurs pour nous aider à résoudre de nombreux problèmes spécifiques. Parce que je suis moi-même un développeur Android et que de nombreux développeurs Android, y compris moi-même, sont les meilleurs en ListView (RecycleView) + BaseAdapter + ArrayList. Les seuls conteneurs que j'utilise habituellement sont ArrayList et HashMap. En conséquence, la compréhension et l’utilisation de l’ensemble du système de conteneurs Java en sont encore à un niveau très superficiel. Si vous ne voulez pas vous épargner et réfléchir à des améliorations, suivez-moi pour résumer les connaissances pertinentes sur les conteneurs Java.

Structure

  • HéritageStructure de la classe conteneur Java

  • Introduction détaillée

    • Liste

    • Définir

    • File d'attente

    • Itération Appareil

    • Collection

    • Carte

  • Quelques suggestions

  • Avancé · Conteneur simultané

    • CopyOnWriteArrayList et stratégie de copie sur écriture

    • ConcurrentLinkedQueue

    • ConcurrentHashMap et technologie de segmentation de verrouillage

    • File d'attente de blocage

Structure d'héritage de la classe de conteneur Java

La bibliothèque de classes de conteneurs Java définit deux conteneurs avec des concepts différents, Collection et Map

  • Collection Une séquence d'éléments indépendants, ces éléments obéissent à un ou plus de règles. La liste doit contenir les éléments dans l’ordre d’insertion. L'ensemble ne peut pas contenir d'éléments en double. La file d'attente détermine l'ordre dans lequel les objets sont générés selon les règles de file d'attente.

(La version du code source Jdk dans l'article est jdk1.8.0_101 sans instructions particulières)

    public interface Collection<E> extends Iterable<E> {
        int size();

        boolean isEmpty();

        boolean contains(Object o);

        Iterator<E> iterator();

        Object[] toArray();

        <T> T[] toArray(T[] a);

        boolean add(E e);

        boolean remove(Object o);

        boolean containsAll(java.util.Collection<?> c);

        boolean addAll(java.util.Collection<? extends E> c);

        boolean removeAll(java.util.Collection<?> c);

        ... //省略了其他方法
    }

Comme vous pouvez le voir, java définit l'interface Collection et les bases des collections internes Méthode de fonctionnement, Collection peut effectuer des opérations telles que l'ajout d'éléments à la fin de la collection et la suppression d'éléments spécifiés par défaut. Les interfaces List, Set et Queue héritent toutes de Collection et définissent différentes méthodes.

  • Carte Un ensemble d'objets "clé-valeur" qui nous permettent de rechercher des valeurs à l'aide de clés.

    public interface Map<K,V> {
        int size();

        boolean containsKey(Object key);

        boolean containsValue(Object value);

        V get(Object key);

        V put(K key, V value);

        V remove(Object key);

        void putAll(java.util.Map<? extends K, ? extends V> m);

        void clear();

        Set<K> keySet();

        Collection<V> values();

        Set<java.util.Map.Entry<K, V>> entrySet();

        interface Entry<K,V> {
            K getKey();

            V getValue();

            V setValue(V value);

            boolean equals(Object o);

            int hashCode();

            ...
        }

        boolean equals(Object o);

        int hashCode();

    }

Interface interne de la carte L'entréeb77a8d9c3c319e50d4b02a976b347910 correspond à la paire clé-valeur de Map.

Introduction en détail

Itérateur

Présentez d'abord l'itérateur. L'itérateur lui-même est également un modèle de conception . L'intention initiale de la conception est qu'il existe de nombreux types d'implémentations de conteneurs, et si nous voulons parcourir le conteneur, nous ne devrions pas nous en soucier. sur l'implémentation du conteneur, d'abord les détails, puis l'opération de traversée doit être légère. Les itérateurs unifient l’accès aux conteneurs et sont peu coûteux à créer. Il convient de noter que les itérateurs ne peuvent se déplacer que dans une seule direction.

    public interface Iterator<E> {
        boolean hasNext();

        E next();

        default void remove() {
            throw new UnsupportedOperationException("remove");
        }

        default void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (hasNext())
                action.accept(next());
            }
    }

Obtenir l'itérateur du conteneur via la méthode iterator() du conteneur
Next() de l'itérateur obtient l'élément suivant
hasNext() détermine s'il y a any elements
remove() supprime l'élément spécifié

ListIterator

ListIterator est une extension de Iterator et est utilisé pour divers accès à la classe List et prend en charge le mouvement bidirectionnel.

Collection

List

List promet de conserver les éléments dans un ordre spécifique. L'interface List ajoute un grand nombre de méthodes basées sur Collection, permettant d'insérer et de supprimer. éléments.

    public interface List<E> extends Collection<E> {

        ...

        boolean add(E e);

        boolean remove(Object o);

        boolean containsAll(Collection<?> c);

        boolean addAll(Collection<? extends E> c);

        boolean addAll(int index, Collection<? extends E> c);

        boolean removeAll(Collection<?> c);

        boolean retainAll(Collection<?> c);

        E get(int index);

        E set(int index, E element);

        void add(int index, E element);

        E remove(int index);

        int indexOf(Object o);

        int lastIndexOf(Object o);

        java.util.List<E> subList(int fromIndex, int toIndex);

        ...

    }

Il existe deux types de liste, ArrayList et LinkedList

Type de liste Avantages Inconvénients Implémentation sous-jacente
ArrayList Les éléments à accès aléatoire sont plus rapides L'insertion et la suppression d'éléments intermédiaires sont plus lentes Array
List类型 优点 缺点 底层实现
ArrayList 随机访问元素较快 中间元素的插入和删除较慢 数组
LinkedList 中间元素的插入和删除,顺序访问的优化 随机访问元素较慢 双向链表
LinkedList Insertion et suppression d'éléments intermédiaires, optimisation de l'accès séquentiel Les éléments à accès aléatoire sont plus lents td> Liste doublement chaînée

Set

Set n'enregistre pas les éléments en double et est généralement utilisé pour des éléments de recherche rapide. Il convient de mentionner que Set a exactement la même interface que Collection sans aucune fonctionnalité supplémentaire. Les éléments stockés doivent définir la méthode equals()

Set类型 使用场景 底层实现
HashSet 快速查找,元素必须定义hashCode() 链表
TreeSet 保持次序,元素必须实现Comparable接口 红-黑树结构
LinkedHashSet 维护次序的HashSet, 元素必须定义hashCode() 链表

Queue

除了并发应用,Queue仅有的两个实现是LinkedList和PriorityQueue, 其中LinkedList同时实现了List, Deque接口。它们的差异在于排序行为而不是性能。

    public interface Queue<E> extends Collection<E> {
        boolean add(E e);

        boolean offer(E e);

        E remove();

        E poll();

        E element();

        E peek();
    }

Map

Map类型 使用场景 底层实现
HashMap 快速查询 散列表
LinkedHashMap 迭代遍历具有顺序(插入顺序 or 最近最少使用) 链表
TreeMap 具有排序,唯一可以返回子树的Map(subMap()) 红-黑树结构
WeakHashMap 弱键映射,映射之外无引用的键,可以被垃圾回收 散列表
ConcurrentHashMap 线程安全的Map 链表
IdentityHashMap 使用==代替equals()对键进行排序,专位解决特殊问题 链表

Nous pouvons ajuster manuellement HashMap pour ajuster les performances, impliquant des concepts tels que la capacité, la capacité initiale, la taille, le facteur de charge, etc. Si vous êtes intéressé, vous pouvez lire quelques informations pertinentes.

Quelques suggestions

  • N'utilisez pas de conteneurs obsolètes tels que la pile de table de hachage d'énumération vectorielle (oui, c'est la mauvaise conception originale de Java. Si vous utilisez la pile dans pratique, LinkedList est recommandé)

Avancé · Concurrent Conteneur

Je ne discuterai pas de la mise en œuvre détaillée ici, je présenterai simplement brièvement les connaissances de base. Si vous êtes intéressé, vous pouvez lire le livre "Java Concurrent Programming" Art".

CopyOnWriteArrayList et stratégie de copie sur écriture

La copie sur écriture, appelée COW, est une stratégie d'optimisation utilisée en programmation. L'idée de base est que tout le monde partage le même contenu depuis le début. Lorsque quelqu'un souhaite modifier le contenu, il le copie pour former un nouveau contenu, puis le modifie. C'est une sorte de stratégie de paresse différée. À partir du JDK 1.5, le package de concurrence Java fournit deux conteneurs simultanés implémentés à l'aide du mécanisme CopyOnWrite, à savoir CopyOnWriteArrayList et CopyOnWriteArraySet. Le conteneur CopyOnWrite est très utile et peut être utilisé dans de nombreux scénarios simultanés.

Le conteneur CopyOnWrite est un conteneur qui est copié lors de l'écriture. La compréhension populaire est que lorsque nous ajoutons des éléments à un conteneur, nous ne les ajoutons pas directement au conteneur actuel, mais copions d'abord le conteneur actuel pour créer un nouveau conteneur, puis ajoutons des éléments au nouveau conteneur. Pointez ensuite la référence du conteneur d'origine vers le nouveau conteneur. L'avantage de ceci est que nous pouvons effectuer des lectures simultanées sur le conteneur CopyOnWrite sans verrouillage, car le conteneur actuel n'ajoutera aucun élément. Par conséquent, le conteneur CopyOnWrite est également une idée de séparation de la lecture et de l'écriture, et la lecture et l'écriture sont des conteneurs différents.

Le conteneur CopyOnWrite ne peut garantir que la cohérence finale des données, mais ne peut garantir la cohérence en temps réel des données. Donc, si vous souhaitez que les données écrites soient lues immédiatement, veuillez ne pas utiliser le conteneur CopyOnWrite.

ConcurrentLinkedQueue

En programmation simultanée, vous devez parfois utiliser des files d'attente ou des listes thread-safe. Il existe généralement deux manières d'assurer la sécurité des threads, l'une consiste à utiliser des algorithmes de blocage et l'autre consiste à utiliser des algorithmes non bloquants. La base de la mise en œuvre de l'algorithme non bloquant est la boucle CAS (Comparaison et échange Compare and Swipe).

L'implémentation technique de ConcurrentLinkedQueue est similaire à CopyOnWriteArrayList et Copy, mais seule une partie du contenu du conteneur peut être copiée et modifiée au lieu de l'intégralité du conteneur. ConcurrentLinkedQueue se compose d'un nœud principal et d'un nœud de queue. Chaque nœud se compose d'un élément de nœud (élément) et d'une référence pointant vers le nœud suivant (suivant). Les nœuds sont associés via next pour former une file d'attente avec une structure de liste chaînée.

ConcurrentHashMap et technologie de segmentation de verrous

ConcurrentHashMap est un HashMap thread-safe et efficace. Dans un environnement multithread, l'utilisation d'un HashMap non thread-safe entraînera une boucle infinie et, comme suggéré dans l'article, les conteneurs obsolètes tels que HashTable sont inefficaces (utilisez synchronized pour garantir que le thread sécurité). ConcurrentHashMap utilise la technologie de segmentation des verrous pour améliorer considérablement l'efficacité de l'utilisation simultanée.

Technologie de segmentation des verrous : supposons que le conteneur dispose de plusieurs verrous et que chaque verrou est utilisé pour verrouiller une partie des données dans le conteneur. Lorsque plusieurs threads accèdent à différents segments de données du conteneur, il y a. pas de verrouillage entre les threads. Concurrence pour améliorer l’efficacité des accès simultanés.

File d'attente de blocage

JDK7 fournit 7 files d'attente de blocage, et les principes de mise en œuvre sont tous basés sur le modèle production-consommation en attente d'un mécanisme de notification.

ArrayBlockingQueue
Type de file d'attente bloquante Fonctionnalités
File d'attente de blocage limitée composée d'une structure de tableau
LinkedBlockingQueue File d'attente de blocage limitée composée d'une structure de liste chaînée
PriorityBlockingQueue Prend en charge la Priorité
阻塞队列类型 特点
ArrayBlockingQueue 由数组结构组成的有界阻塞队列
LinkedBlockingQueue 由链表结构组成的有界阻塞队列
PriorityBlockingQueue 支持优先级排序的无界阻塞队列
DelayQueue 使用优先级队列实现的无界阻塞队列
SynchronousQueue 不储存元素的阻塞队列
LinkedTransferQueue 由链表结构组成的无界阻塞队列
LinkedBlockingQueue 由链表结构组成的双向阻塞队列
File d'attente de blocage illimitée triée
DelayQueue File d'attente de blocage illimitée implémentée à l'aide de la file d'attente prioritaire
SynchronousQueue Une file d'attente de blocage qui ne stocke pas d'éléments
LinkedTransferQueue Une file d'attente de blocage illimitée composée d'une structure de liste chaînée
LinkedBlockingQueue Une file d'attente de blocage bidirectionnelle composée d'une structure de liste chaînée

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

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