1. Collections à Java
Les cours de collecte en Java sont les classes les plus fréquemment utilisées et les plus pratiques de la programmation Java. En tant que classe de conteneurs, la classe de collecte peut stocker n'importe quel type de données, et bien sûr, il peut également stocker des types spécifiés en combinaison avec des génériques (mais les génériques ne sont valables que pendant la période de compilation et seront effacés au moment de l'exécution). Ce qui est stocké dans la classe de collection n'est qu'une référence à l'objet, pas une référence à l'objet lui-même. La capacité de la classe de collecte peut être étendue dynamiquement pendant le fonctionnement et fournit également de nombreuses méthodes pratiques, telles que la recherche de l'union et l'intersection de la collection.
2. Structure de classe de collecte
Les collections en Java comprennent plusieurs structures de données, telles que les listes liées, les files d'attente, les tables de hachage, etc. En termes de structure d'héritage d'une classe, il peut être divisé en deux catégories. L'un est hérité de l'interface de collection. Ce type de collection comprend des classes de collecte telles que la liste, le set et la file d'attente. L'autre classe est héritée de l'interface MAP, qui comprend principalement des classes de collecte liées aux tables de hachage. Jetons un coup d'œil aux diagrammes de structure d'héritage de ces deux catégories:
1. Liste, définition et file d'attente
La ligne pointillée verte de la figure représente l'implémentation, la ligne continue verte représente l'héritage entre les interfaces et la ligne continue bleue représente l'héritage entre les classes.
(1) Liste: nous utilisons plus de listes, y compris ArrayList et LinkedList. La différence entre ces deux est également très évidente, ce qui peut être vu à partir de leurs noms. La liste Array sous-jacente est implémentée via des baies, donc sa vitesse d'accès aléatoire est relativement rapide, mais l'efficacité est relativement faible pour les cas où des ajouts et des suppressions fréquents sont nécessaires. Pour LinkedList, la couche sous-jacente est implémentée via des listes liées, de sorte que l'opération d'addition et de suppression est plus facile à compléter, mais l'efficacité de l'accès aléatoire est relativement faible.
Examinons d'abord l'efficacité d'insertion des deux:
package com.paddx.test.collection; import java.util.arraylist; import java.util.linkedList; public class listTest {public static void main (string [] args) {for (int i =; i <; i ++) {} long start = newdlist = newdlist = newdlist = New LinkedList <Integer> (); for (int i =; i <; i ++) {linkedList.add (, i);} long fin = system.currenttimemillis (); system.out.println (end - start); arrayList <nteger> arrayList = new ArrayList <nteger> (); pour (intraList> i =; i <; i ++) {arrayList.add (, i);} System.out.println (System.CurrentTimeMillis () - end);}}Voici les résultats de l'exécution locale:
vingt-trois
1227
On peut voir que dans ce cas, l'efficacité d'insertion de Linkedlist est beaucoup plus élevée que celle de ArrayList, bien sûr, il s'agit d'une situation relativement extrême. Comparons l'efficacité de l'accès aléatoire entre les deux:
package com.paddx.test.collection; import java.util.arraylist; import java.util.linkedlist; import java.util.random; public class listTest {public static void main (String [] args) {random random = new random (); for (int i =; i ++) {} lienList liked <Integer> likedliSe = New LinkedList <Integer> (); for (int i =; i <; i ++) {linkedList.add (i);} ArrayList <Integer> arrayList = new ArrayList <Integer> (); for (int i =; i <; i ++) {arrayList.add (i);} long start = System.currentTimeMillis (); for (int i =; i <; i ++) {int j = random.nextint (i +); int k = linkedList.get (j);} long fin = system.currenttimemilis (); system.out.println (end - start); for (int i =; i <; i ++) {int j = random.nextint (i +); int k = ArrayList.get (J);} System.out.println (System.CurrentTimemillis () - end);}}Voici le résultat de mon exécution:
5277
6
Il est évident que l'efficacité d'accès aléatoire d'ArrayList est plusieurs ordres de grandeur supérieure à LinkedList. Grâce à ces deux pièces de code, nous devrions être en mesure de savoir plus clairement la différence entre LinkedList et ArrayList et les scénarios d'adaptation. En ce qui concerne le vecteur, il s'agit d'une version en filetage de ArrayList, tandis que Stack correspond à la structure de données de pile. Ces deux sont utilisés moins fréquemment, donc je ne donnerai pas d'exemple ici.
(2) Fitre: Généralement, cela peut être fait directement à l'aide de LinkedList. Il peut également être vu à partir du diagramme de classe ci-dessus que LinkedList hérite de Deque, donc LinkedList a la fonction d'une file d'attente à double extrémité. PriorityQueue se caractérise en offrant une priorité pour chaque élément, et les éléments avec une priorité élevée seront prioritaires de la file d'attente.
(3) SET: La principale différence entre l'ensemble et la liste est que le jeu ne permet pas de répéter les éléments, tandis que la liste peut permettre la répétition des éléments. Pour juger de la répétition des éléments, nous devons décider en fonction de la méthode de hachage de l'objet et de la méthode égale. C'est aussi pourquoi nous employons généralement la méthode HashCode et égal à la méthode pour les classes d'éléments dans une collection. Prenons un exemple pour voir la différence entre l'ensemble et la liste, ainsi que le rôle de la méthode HashCode et Equals Method:
package com.paddx.test.collection; import java.util.arraylist; import java.util.hashset; import java.util.set; public class settest {public static void main (string [] args) {personne p1 = new personne ("lxp", 10); personne p2 = new-personne ("lxp", 10); personne P3 = new Personne ("lxp", 20); arrayList <onon> list = new ArrayList <onon> (); list.add (p1); System.out.println ("--------------"); list.add (p2); System.out.println ("----------------") List.Size ()); System.out.println ("---------------"); set <onge> set = new Hashset <shon> (); set.add (p1); Systems.out.println ("------------"); set.add (p2); size = "+ set.size ());} classe de classe statique {nom de chaîne privée; int privé; ! = o.getClass ()) return false; personne personne = (personne) o; return name.equals (personne.name);} @ overRidepublic int hashcode () {System.out.println ("call hashcode (), age =" + age); return âge;}}} Les résultats d'exécution du code ci-dessus sont les suivants:
------------
------------
Taille de liste = 3
---- diviser la ligne ----
Appelez HashCode (), Age = 10
------------
Appelez HashCode (), Age = 10
Appeler equals (); name = lxp
------------
Appeler hashcode (), âge = 20
Set Size = 2
À partir des résultats, aucune opération supplémentaire n'est effectuée lorsque l'élément est ajouté à la liste et peut être répété. Avant de rejoindre Set, vous devez d'abord exécuter la méthode HashCode. Si la valeur renvoyée existe déjà dans l'ensemble, vous devez continuer à exécuter la méthode Equals. Si le résultat renvoyé par la méthode Equals est également vrai, il prouve que l'élément existe déjà et que le nouvel élément sera écrasé par l'ancien élément. Si la valeur de code de hash renvoyé est différente, vous ajouterez directement l'ensemble. N'oubliez pas ici que pour les éléments d'une collection, les éléments avec différentes valeurs de code de hash doivent être inégaux, mais pour les éléments avec un inégal, les valeurs de code de hash peuvent être les mêmes.
La différence entre Hashset et LinkedHashset est que ce dernier peut garantir que l'ordre des éléments insérés dans l'ensemble est cohérent avec l'ordre de sortie. La différence entre Tresset est que sa sorte est triée en comparateur, et par défaut, il est organisé par ordre croissant dans l'ordre naturel des caractères.
(4) ITable: De cette figure, vous pouvez voir que la classe de collection hérite d'Itable. La fonction de cette interface consiste à fournir une traversée d'éléments, c'est-à-dire que toutes les classes de collecte (sauf les classes liées à la carte) fournissent des fonctions de traversée d'élément. ITable contient iterator d'Iterator, et son code source est le suivant. Si vous connaissez le mode itérateur, il devrait être facile à comprendre.
Interface publique Iterator <e> {boolean hasnext (); e Next (); void reous ();}2. Carte:
Le plus grand avantage de la collection de types de cartes est que son efficacité de recherche est relativement élevée et que la complexité du temps d'O (1) peut être réalisée idéalement. La carte la plus couramment utilisée est le hashmap. La différence entre LinkedHashmap et HashMap est que le premier peut garantir que l'ordre des éléments insérés dans l'ensemble est cohérent avec l'ordre de sortie. La différence entre ces deux et Treemap est que Treemap est trié en fonction des valeurs clés. Bien sûr, sa mise en œuvre sous-jacente a également des différences essentielles. Par exemple, la couche sous-jacente de hashmap est une table de hachage, tandis que la couche sous-jacente de Treemap est un arbre. Voyons maintenant la différence entre Treemap et LinkedHashmap:
package com.paddx.test.collection; import java.util.iterator; import java.util.linkedhashmap; import java.util.map; import java.util.treemap; public classe Maptest {public static net main (String [] args) {Map <String> Treemap = New Treemap <String, String,); LinkedMap = new LinkedHashMap <String, String> (); Treemap.put ("b", null); Treemap.put ("C", null); Treemap.put ("a", null); for (iterator <string> iter = Treemap.KeySet (). Iterator (); iter.hasnext ();) {System.out.println ("Treemap =" + iter.next ());} System.out.prin tln ("---------- 分割线 ---------"); linkedmap.put ("b", null); linkedmap.put ("c", null); linkedmap.put ("a", null); pour (Iterator <string> iter = linkedmap.keyset (). Iterator (); iter.hasnext ();) {System.out.println ("LinkedHashmap =" + iter.next ());}}} Exécutez le code ci-dessus et le résultat d'exécution est le suivant:
Treemap = A
Treemap = B
Treemap = C
-------------------------
LinkedHashMap = B
LinkedHashmap = C
LinkedHashMap = A
D'après les résultats en cours d'exécution, il est évident que la différence entre Treemap et LinkedHashMap est clairement observée. Le premier est sorti par tri de chaînes, tandis que le second est sorti par ordre d'insertion. Des lecteurs attentifs peuvent constater que la différence entre HashMap et Treemap est cohérente avec les différences mentionnées précédemment entre Hashset et Treeset. Lorsque vous effectuez une analyse du code source à l'avenir, nous pouvons voir que HashSet et Treeset sont essentiellement mis en œuvre via HashMap et Treemap respectivement, donc leurs différences sont naturellement les mêmes. Le hashtable est rarement utilisé maintenant. La principale différence par rapport à Hashmap est que le hashtable est en sécurité, mais en raison de sa faible efficacité, le hashmap est généralement utilisé. Dans un environnement multi-thread, CurrentHashMap est généralement utilisé à la place.
3. Résumé
Cet article ne présente que le cadre de la collection Java et sa relation d'héritage dans son ensemble. En plus des classes ci-dessus, les collections fournissent également deux classes d'outils: les collections et les tableaux. De plus, le tri dans la collection est étroitement lié à comparable et à comparateur. Dans un article ultérieur, le code source de mise en œuvre de la classe ci-dessus dans JDK sera analysé en détail.