java apprendre à améliorer vingt-deux: conteneurs détaillés (cinq) analyse de code source HashMap (sur)

Prêt depuis longtemps, enfin clarifié la pensée, le courage, j'ai commencé à introduire le protagoniste Benpian --HashMap. Pour être honnête, ce gars peut dire trop de contenu, et si comme avant ArrayList comme traducteur à la source, au centre de parler un peu, assurez-vous de faire beaucoup de gens se gratter la tête, et non pas les choses compliquées aussi simple que possible avec une façon de le dire, que cela signifie parler de l'échec très (paroi frontale

). Cette fois-ci a décidé d'expliquer le contenu de quatre points,

La première partie explique principalement la structure HashMap, des paramètres importants et de façon importante, et ont besoin d'attention de rémunération et scénarios d'utilisation.

Le deuxième grand algorithme de hachage HashMap pour expliquer la fonction de perturbation et de l'expansion de la fonction. algorithme d'analyse approfondie dans laquelle la beauté du nud plus commun.

HashMap Partie III principalement sur la entrySet, KeySet et valeurs.

la structure TreeNode et la restructuration de la route lorsque les éléments principalement sur l'augmentation ou la diminution du titre IV du HashMap. (Avec JDK8 dans l'arbre rouge-noir pour expliquer).

Parce que le HashMap peut parler des points trop, ici sélectionner les points les plus importants seront décrits, quatre de l'angle et la profondeur de chacun est différent, donc les différentes étapes des élèves peuvent également choisir de lire des sections différentes, la première facile à comprendre des articles appartenant à la section primaire, le deuxième, le titre III et le titre IV appartient à la HashMap section avancée si la difficulté à lire, vous pouvez sauter, puis à lire plus tard.

Bon, homme de peu de mots dit, et puis dans notre thème.

Cet article traite avant d'abandonner l'argument, des centaines de lignes de code source mis directement est trop sec, il faut aller un peu plus la digestion humide (drôle), le prochain sera expliqué avec du texte et des images.

En manuel, vous soigneusement en apprendre davantage sur les questions suivantes:

Quelle est la structure 1.HashMap?

Quelles sont les forces et les faiblesses de 2.HashMap?

3. Quand faut-il utiliser HashMap?

4.HashMap méthode commune dans laquelle d'avoir?

Qu'est-ce 5.HashMap la méthode get () méthode fonctionne et PUT () est?

6.HashMap dans la détection de collision (détection de collision) et quel impact est la solution?

7. Si la taille de HashMap dépasse le facteur de charge (facteur de charge) de capacité définie, comment faire?

8. Définir la clé HashMap est ce qui a besoin d'attention? Vous pouvez utiliser des objets personnalisés comme clés font?

Ah, si le contenu est encore beaucoup de, beaucoup de produits secs. look Let à un peu HashMap châtaignier:

Public class Test { public static void main (String args) { carte < String, Entier >  Carte = new HashMap (); map.put ( "Bob", 66); map.put ( "Li", 77); map.put ( "rouge", 88); map.put ( "Xiaogang", 89); map.put ( "peu de puissance", 90); map.put ( "Wang", 91); map.put ( "Huang", 92); map.put ( "Little Green", 93); map.put ( "peu de vert", 94); map.put ( "noir", 95); map.put ( "small bleu", 96); map.put ( "petit violet", 97); map.put ( "petite orange", 98); map.put ( "petit rouge", 99); map.put ( "Frank", 100); pour (Map.Entry < String, Entier >  entrée: map.entrySet ()) { System.out.println (entry.getKey () + ":" + entry.getValue ()); } } }

La sortie est également très simple:

Xiaogang: 89 Petit orange: 98 Little Blue: 96 Petite force: 90 Xiaoqing: 93 Noir: 95 Xiao Ming: 66 Li: 77 Wang: 91 Petit violet: 97 Rouge: 88 Little Green: 94 Frank: 100 Xiao Huang: 92 Petit rouge: 99

On peut voir que certains HashMap stockées dans l'ordre placé avec nous ne sont pas les mêmes, mais les résultats sont les mêmes pour chaque passage à une sortie étonnante de l'ordre, pourquoi est-ce ainsi? Ne vous inquiétez pas, nous allons faire une pause et voir.

 Vous pouvez voir, ce objets HashMap, il y a un champ de table, vous pouvez voir qu'il est un tableau, nous mettons information sur le rendement, tout cela à l'intérieur de gars, vous voyez, cet ordre avec la sortie ci-dessus pour n'est pas très comme?

Mais, attendez une minute, vous ne trouvez pas, Mike, petit violet, petit manque rouge. . Ce problème, ne vous inquiétez pas, nous serons ensemble pour les trouver.

HashMap où la structure de données est une liste liée sous la forme d'un tableau à + noeuds de stockage, chaque noeud d'une paire de valeurs de clé (Node < K, V > ) Stockée sous la forme, voir le tableau ci-dessus, la valeur est stockée dans la table de hachage locale, sa structure de données est telle que: Noeud < K, V > Tableau, que ce nud à la fin est ce qui est? look Let à son code:

 / ** * La plupart nud ordinaire pour les paires valeur clé * / Noeud de classe statique < K, V >  met en uvre Map.Entry < K, V >  { hachage final int; clé finale K; La valeur V; / ** * Point de référence au noeud suivant * / nud < K, V >  suivant; Noeud (hachage int, la clé K, la valeur de V, Noeud < K, V >  suivant) { this.hash = hash; this.key = clé; this.value = valeur; this.next = suivant; } public final K getKey () {touche de retour;} getValue public final V () {valeur de retour;} public final String toString () {touche de retour + "=" + valeur;} public final int hashCode () { // renvoie le résultat OU exclusif opération de la valeur de hachage de la clé et de la valeur retour Objects.hashCode (clé) ^ Objects.hashCode (valeur); } setValue (V newValue) public final V { V oldValue = valeur; value = nouvelleValeur; retourner oldValue; } finale égaux booléennes publics (Object o) { if (o == this) return true; si (o instanceof Map.Entry) { Map.Entry < ?,? >  e = (Map.Entry < ?,? > ) O; si (Objects.equals (clé, e.getKey ()) && Objects.equals (valeur, e.getValue ())) return true; } return false; } }

classe Node hérite d'une interface à Map.Entry, s'il n'y a aucune impression de cette interface qui peut revenir en arrière et regarder le contenu de l'interface Carte, le contenu du nud est très simple, hachage, des informations clés et une référence au noeud suivant, il est entre noeud ils sont reliés pour former une chaîne par cette référence. Pensez structure de table, Noeud < K, V > , Maintenant est de ne pas comprendre ce qui est un tableau + liste chaînée de stockage?

Quoi? Dire cela ne suffit pas d'image? Eh bien, une image vaut mille mots, avant de dire d'utiliser des illustrations façon d'expliquer, il est donc le point de vue de quelques photos:

 Ah, nous enregistrons des données en mémoire est comme ça, nous allons voir un point d'arrêt dans les données:

 Vous devriez être en mesure de comparer les deux chiffres plus de compréhension claire, qui peut être vu à l'intérieur de l'ordre du tableau ne sont pas stockées, et beaucoup de seaux vides (chaque grille est appelée un bac, traduit dans la baignoire où la mauvaise

) Pourquoi serait-il un tel ordre? look Let à elle mettre des méthodes:

/ ** * La clé spécifiée de la carte et la valeur à associer, si la carte dans la cartographie clé existe déjà, l'ancienne valeur sera remplacée. * Retourne l'ancienne valeur de l'affectation des touches, si le mappage clé n'existe pas, alors NULL est renvoyée. * / mettre publique V (touche K, la valeur V) { retour putVal (hachage (clé), clé, valeur, false, true); } / ** * Réaliser Map.put et méthodes connexes * * Hachage @param valeur clé de hachage * @Param touche clé * Clé de valeur @param sera la valeur mappée * @Param onlyIfAbsent Si cela est vrai, il ne changera pas la valeur existante * Evict @param Si ce paramètre est vrai, puis insérez une nouvelle valeur chaque, sera le premier élément de la liste des meilleurs sur le nombre d'éléments de la liste restent inchangés * / finale V putVal (de hachage int, la clé K, la valeur de V, boolean onlyIfAbsent, evict Boolean) { nud < K, V > Tab; Noeud < K, V >  p; int n, i; // Si la table en cours n'est pas initialisé, la première redimensionnées à la capacité initiale if ((tab = tableau) == null || (n = tab.length) == 0) . N = (tab = redimensionnement ()) de longueur; // (n-1) et hachage ce lieu qui est basé sur hachage recherche numéro de série, hachage veulent apprendre le contenu plus connexes peuvent être consultés sous if ((p = onglet ) == NULL) // n'existe pas, créez un nouveau noeud patte  = Newnode (hachage, la clé, la valeur, null); else { nud < K, V >  e; K k; // D'abord trouver le noeud correspondant si (== p.hash hachage && ((K = p.key) == || clé (clé! = NULL && key.equals (k)))) e = p; else if (p instanceof TreeNode) // Si le nud de l'arbre, puis appelez la méthode appropriée putVal // todo putTreeVal e = ((TreeNode < K, V > ) P) .putTreeVal (cet onglet, hachage, clé, valeur); else { // Si la liste est parcourue pour trouver entre pour (int binCount = 0 ;; ++ binCount) { if ((e = p.next) == NULL) { // si elle est introuvable sur cette liste, puis créer un nouveau nud à la dernière pendaison p.next = newNode (hachage, la clé, la valeur, null); si (binCount > = TREEIFY_THRESHOLD - 1) // -1 pour le 1er // Si la longueur de la chaîne atteint la longueur maximale de l'arbre, l'arbre de conduite // todo treeifyBin treeifyBin (tab, hachage); break; } if (e.hash == hachage && ((K = e.key) == || clé (clé! = NULL && key.equals (k)))) break; p = e; } } // Si le mappage, la valeur de la clé existe déjà à remplacer if (e! = null) {// mapping existant pour la clé V = oldValue e.value; if (! onlyIfAbsent || oldValue == null) e.value = valeur; afterNodeAccess (e); retourner oldValue; } } // ajouter un certain nombre de modifications ++ modCount, si (++ taille >  seuil) redimensionner (); afterNodeInsertion (evict); return null; }

De là, vous pouvez voir la logique à l'élément additif HashMap:

La clé de hashCode () pour faire un hachage (fonction de hachage, le contenu spécifique d'une explication), et la valeur de hachage est calculée sur la base de cet indice (i = (n - 1) et hachage);

Si la collision (collision de hachage) ne se produit pas, directement dans le seau;

Si la collision, sous la forme d'une liste chaînée suspendue derrière la baignoire;

Si la liste est trop longue à cause de collisions entraînent (supérieur ou égal TREEIFY_THRESHOLD), mettre la liste est convertie en arbres rouge-noir;

Si le nud existe déjà sur le remplacement de la valeur ancienne (garantir l'unicité de la clé)

Si le seau est plein (plus que le facteur de charge de la capacité actuelle *), nous devons redimensionner (Redimensionner et re-hachage).

 Peut-être que vous voulez savoir la table est quelque chose que nous examinons la façon dont plusieurs membres importants de variables, il:

/ * * Champ -------------- ---------------- / / ** * Table de hachage dans l'utilisation initiale d'une initialisation, et d'ajuster en fonction de la taille. Lors de la distribution, la longueur est toujours une puissance de 2 * * Structure Todo hashmap * Todo transitoire * / Noeud transitoire < K, V > Tableau; / ** * Enregistrer cache entrySet, attention AbstractMap dans le domaine est un keySet () et les valeurs (). * / transitoires Set < Map.Entry < K, V > >  entrySet; / ** * Carte du nombre de paires valeur clé * / int size transitoire; / ** * Numéro de hashmap de modifications structurelles, des moyens de modification de structure changeant le nombre de carte hashmap ou de modifier la structure interne. * Ce champ est utilisé pour créer un ensemble de vues peut échouer rapidement (fail-rapide) iterator HashMap. * / transitoire int modCount; / ** * La valeur suivante de l'ajustement de taille (facteur de charge de la capacité de *). * / seuil int; / ** * Hashmap facteur de charge * / finale loadfactor flottant;

champs de la table sont stockées dans les données, le type de nud est un tableau, la structure de nud est simple, et mémoriser simplement la valeur de clé, et un noeud à un point de référence et la clé de hachage.

 / ** * La plupart nud ordinaire pour les paires valeur clé * / Noeud de classe statique < K, V >  met en uvre Map.Entry < K, V >  { hachage final int; clé finale K; La valeur V; / ** * Point de référence au noeud suivant * / nud < K, V >  suivant; Noeud (hachage int, la clé K, la valeur de V, Noeud < K, V >  suivant) { this.hash = hash; this.key = clé; this.value = valeur; this.next = suivant; } public final K getKey () {touche de retour;} getValue public final V () {valeur de retour;} public final String toString () {touche de retour + "=" + valeur;} public final int hashCode () { // renvoie le résultat OU exclusif opération de la valeur de hachage de la clé et de la valeur retour Objects.hashCode (clé) ^ Objects.hashCode (valeur); } setValue (V newValue) public final V { V oldValue = valeur; value = nouvelleValeur; retourner oldValue; } finale égaux booléennes publics (Object o) { if (o == this) return true; si (o instanceof Map.Entry) { Map.Entry < ?,? >  e = (Map.Entry < ?,? > ) O; si (Objects.equals (clé, e.getKey ()) && Objects.equals (valeur, e.getValue ())) return true; } return false; } }

collection Cache d'entrée dans les variables membres dans entrySet (en fait, si vous regardez attentivement, vous trouverez un des éléments de stockage logiques entrySet n'est pas simple, il vous expliquera dans la partie III). représente un seuil pour le prochain seuil ajusté re-(charge facteur de capacité *), le degré maximum de la table réimprimer facteur de remplissage indique la valeur par défaut est de 0,75, à savoir, lorsque la capacité est épuisée à l'expansion de 75% déclenchera, parce que lorsque l'élément de table est suffisante depuis longtemps, la probabilité de conflit sera considérablement augmenté, le conflit conduit à un nombre accru d'éléments dans chaque augmentation du godet, donc vous permettra de trouver l'efficacité de l'élément devient faible, lorsque le godet 8 lorsque le même nombre d'éléments à atteindre, des éléments de structure du godet sont converties en arbre rouge-noir.

Donc, la question est, pourquoi est-8 au lieu de 6 ou 7, 10 faire? ? ?

Si vous voulez discuter de ce sujet en profondeur, puis, je dois dire que sur celui-là. . . Ici, je vais citer ce que les annotations JDK8 dans le HashMap:

* Idéalement, sous hashcodes aléatoires, la fréquence des * Les nuds dans les bacs suit une distribution de Poisson * (Http://en.wikipedia.org/wiki/Poisson_distribution) avec * Paramètre d'environ 0,5 en moyenne pour le redimensionnement par défaut * Seuil de 0,75, mais avec une grande variance à cause de * Redimensionnement granularité. Ignorer la variance, le rendement attendu * Les occurrences de la taille de la liste k sont (exp (-0,5) * pow (0,5, k) / * Factoriels (k)) Les premières valeurs sont .: * * 0: 0,60653066 * 1: 0,30326533 * 2: 0,07581633 * 3: 0,01263606 * 4: 0,00157952 * 5: 0,00015795 * 6: 0,00001316 * 7: 0,00000094 * 8: 0,00000006 * Plus: moins de 1 sur dix millions *

signifie généralement que, idéalement, HashCode distribution aléatoire, lorsque le facteur de charge est réglé à 0,75, alors la probabilité que le nombre d'éléments dans la cuve est sensiblement 0,5 distribution de Poisson, le nombre d'éléments dans les tronçons de baignoire dix millions de probabilité de moins de 8 minutes , parce que la conversion en arbre rouge-noir est assez de temps et de l'exploitation de main-d'uvre, ne veulent pas naturellement régulière, mais si trop élevé, serait dénué de sens pour définir la valeur.

Ainsi, la question à nouveau. . Pourquoi 0,75, au lieu de 0,5, 0,8? ? ? Ceci est une valeur empirique, un coût de Compromis dans l'espace et le temps, comme la capacité initiale par défaut est réglé sur 16. Notes JDK8 regard sur le début du HashMap peut trouver la réponse :( Pour être honnête, JDK notes vraiment trop trop détaillées, des manuels scolaires la plupart des gens qui écrire du code ou non le même)

 * < p > En règle générale, le facteur de charge par défaut (.75) offre un bon * Compromis entre le temps et les coûts d'espace. Des valeurs plus élevées diminuent la * Les frais généraux de l'espace, mais augmenter le coût des recherche (reflétée dans la plupart des * Les opérations de la < tt > HashMap < / Tt >  classe, y compris * < tt > get < / Tt >  et < tt > mettre < / Tt > ). Le nombre prévu d'entrées dans * La carte et son facteur de charge doivent être pris en compte lors de la * Réglage de sa capacité initiale, de manière à minimiser le nombre de * Les opérations de resucée. Si la capacité initiale est supérieure à la * Nombre maximum d'entrées divisé par le facteur de charge, pas de ressasser * Les opérations se produira jamais.

Une fois la traduction à nouveau merdiques:

  • En règle générale, le facteur de charge par défaut (0,75) est en bon temps et l'espace de compromis coût. Si la valeur à une valeur plus élevée, même si elle
  • Réduire l'espace aérien, mais il augmentera le coût de la recherche (dans la plupart des opérations HashMap de réaction, y compris les méthodes get et mises).
  • Lorsque le réglage de la capacité initiale, vous devez tenir compte du nombre d'entrées dans la cartographie, et le facteur de charge pour réduire au minimum le nombre de re-hachage.
  • Si la capacité initiale supérieur au nombre maximum d'entrées divisé par le facteur de charge, il ne se produira pas à nouveau l'opération de hachage.

De plus, le chargement et la capacité sont des facteurs qui peuvent être spécifiées dans le constructeur:

 / ** * Un hashmap vide avec la capacité initiale spécifiée et la structure de facteur de charge, * / HashMap publique (int initialCapacity, loadfactor float) { si (initialCapacity <  0) throw new IllegalArgumentException ( "capacité initiale illégale:" + initialCapacity); si (initialCapacity >  MAXIMUM_CAPACITY) initialCapacity = MAXIMUM_CAPACITY; si (loadfactor < = 0 || Float.isNaN (loadfactor)) throw new IllegalArgumentException ( "facteur de charge illégale:" + loadfactor); this.loadFactor = loadfactor; // seuil recalculé this.threshold = tableSizeFor (initialCapacity); } / ** * Avec la capacité initiale spécifiée et un facteur de charge par défaut (0,75) Construit un vide hashmap * / HashMap publique (int initialCapacity) { ce (initialCapacity, DEFAULT_LOAD_FACTOR); } / ** * Avec la capacité spécifiée par défaut (16) et un facteur de charge par défaut (0,75) Construit un vide hashmap * / HashMap publique () { this.loadFactor = DEFAULT_LOAD_FACTOR; // tous les autres champs en défaut } / ** * Avec une autre pour construire une nouvelle carte hashmap, et de garder la même mappage. La nouvelle HashMap en utilisant un facteur de charge par défaut (0,75) et conçu pour répondre à tous le mappage pour la carte spécifiée * La capacité initiale. * / HashMap publique (Carte < ? Prolonge K ,? Prolonge V >  m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries (m, false); }

Si vous ne spécifiez pas une taille initiale et le facteur de charge, la valeur par défaut et le facteur de charge par défaut de la capacité, et est HashMap utiliser le chargement paresseux de conduite, initialise la table où ils sont vraiment ajouter des éléments à l'intérieur. Au-dessus, nous avons vu la réalisation de la méthode de vente, nous regardons comment obtenir la méthode est mise en uvre:

 / ** * Renvoie la valeur de la carte clé, la clé n'existe pas lorsque le return null * / get public V (Object key) { nud < K, V >  E; ? Retour (e = GetNode (hachage (clé), clé)) == null null: e.value; } / ** * Met en uvre et des méthodes connexes map.get * / Noeud finale < K, V >  GetNode (Hash int, Object key) { nud < K, V > Tab; Noeud < K, V >  en premier lieu, e; int n; K k; if ((tab = tableau)! = null && (n = tab.length) >  0 && (First = onglet )! = Null) { // déterminer si le premier noeud si (first.hash == hachage && // vérifie toujours le premier noeud ((K = first.key) == || clé (clé! = NULL && key.equals (k)))) retourner le premier; if ((e = first.next)! = null) { if (premier instanceof TreeNode) // Si un nud de l'arbre, la méthode par getTreeNode TreeNode pour trouver la clé correspondante retour ((TreeNode < K, V > ) Tout d'abord) .getTreeNode (hachage, clé); do { // sinon parcourir la liste pour trouver if (e.hash == hachage && ((K = e.key) == || clé (clé! = NULL && key.equals (k)))) retour e; } While ((E = e.next)! = Null); } } return null; }

obtenir l'idée est très simple. idée générale est la suivante:

Seau dans le premier match du premier noeud, un coup direct est retourné;

S'il y a un conflit, puis par key.equals (k) pour trouver l'entrée correspondante

Lorsque l'arbre de noeud, l'arbre à travers key.equals (k) pour trouver la complexité de temps est O (logn);

Si la liste des noeuds est recherché par key.equals (k) dans la liste, la complexité est en O (n).

 Eh bien, les méthodes les plus importantes sont introduites sur, il est temps de sauver grand-père, mal, il est temps de répondre aux questions posées par le début:

Quelle est la structure 1.HashMap?

+ HashMap est stocké dans un tableau de listes liées, par défaut capacité initiale est de 16, le facteur de charge par défaut est de 0,75, alors que la longueur de chaîne atteint 8 sera transformé en arbre rouge-noir pour améliorer l'efficacité de la recherche.

Quelles sont les forces et les faiblesses de 2.HashMap?

avantage HashMap est de trouver rapidement, nous pouvons localiser rapidement un objet à un seau et à la recherche en temps constant. est bien son fort inconvénient - l'algorithme de hachage est la clé de hashcode à charge, donc si la conception clé hashcode suce, il va sérieusement affecter les performances.

 Dans les cas extrêmes, si les valeurs de hachage sont calculées chaque fois la même valeur, la liste est trop long provoquera ensuite converti en un arbre, puis quand les problèmes de hachage d'expansion pauvres effet. À l'autre extrême. Calcul de la valeur de hachage Tous sont des valeurs différentes, alors qui est un tableau d'expansion HashMap continuera, ce qui augmente la capacité de HashMap.

D'autre part, HashMap est thread-safe, si vous souhaitez utiliser dans la HashMap programmation concurrente, il est nécessaire d'utiliser la synchronisation en fonction, la méthode Collections.synchronizedMap () est converti dans le thread-safe HashMap normale, ou en utilisant le package simultané le ConcurrentHashMap être remplacé.

3. Quand faut-il utiliser HashMap?

Parce que HashMap trouver rapidement, afin que les applications ont souvent besoin d'éléments d'accès dans une scène, comme une liste B veulent les éléments à trier en fonction des éléments d'une autre liste A, B devra souvent venir aux éléments A à trouver, mais de trouver généralement utilisé pour traverser la voie, si la prochaine grande liste, l'efficacité est encore à considérer, à ce moment si les éléments stockés dans la carte de B comme un élément clé , l'efficacité de la recherche sera grandement améliorée, ce qui est un espace de stratégie en temps.

4.HashMap méthode commune dans laquelle d'avoir?

Les méthodes courantes mettent, obtenir, putAll, supprimer, clair, remplacer la taille.

Qu'est-ce 5.HashMap la méthode get () méthode fonctionne et PUT () est?

De la clé de hachage hashCode (), et calcule l'indice (n-1 & hachage), pour obtenir ainsi la position de la baignoire. Si la collision de hachage se produit, en utilisant la méthode key.equals () à la liste ou un arbre pour trouver le noeud correspondant.

6.HashMap dans la détection de collision (détection de collision) et quel impact est la solution?

Lorsque les deux éléments clés de la même collision hashCode se produit, comme ci-dessus et Li Xiaoming, en ajoutant après cette période seront suspendus derrière le canon sous la forme d'une liste ou d'un nud d'arborescence.

7. Si la taille de HashMap dépasse le facteur de charge (facteur de charge) de capacité définie, comment faire?

Si la taille est supérieure à la HashMap * facteur de capacité de charge, il fonctionnera pour l'expansion, l'expansion à l'original deux fois.

8. Définir la clé HashMap est ce qui a besoin d'attention? Vous pouvez utiliser des objets personnalisés comme clés font?

clé fournie pour faire usage d'objets immuables, tels que la valeur, chaîne, qui peut assurer la clé immuabilité peut être utilisé pour personnaliser les objets de classe, mais nécessitent une bonne conception de la méthode et égale méthode hashCode.

Ici devrait Applause ici, ce enfin expliquer fini, cette fois-ci parce que les autres fois, n'a pas beaucoup de temps pour écrire un blog, je retardé de deux semaines pour vivre Dites-moi ce que vous, mais écrire un blog passe vraiment temps dans cet article, je pense aussi plusieurs jours comme une bonne idée, des trucs HashMap est trop, les détails sont moins susceptibles d'être exhaustive, mais si tout introduit inéluctablement, alors il est évidemment pas assez simple pour les débutants, il a décidé de scinder en quatre, donc je l'ai lu de manière sélective selon le degré qu'il peut comprendre.

Mais regardez aussi Dites-moi ce que vous récompense un éloge de mes articles sont intéressés sont également toucher des petites mains peu d'attention de bienvenue, ou continuellement mis à jour. Se félicite également de bons conseils, s'il y a des points importants manquants ou mauvais endroit, s'il vous plaît dites-moi ce que vous avez rapidement fait remarquer que plus d'échanges.

Alibaba pionnier de la scène Laboratoire d'intelligence artificielle pour ouvrir une nouvelle connectivité IdO d'entrée
Précédent
Green Lake, chemin changera trois belles, 33 le long d'un lac Tong Tong une scène
Prochain
Avril près de 40 corps à corps, beaucoup d'entre eux plaque rouge continue Yaohao « faible taux de réussite. »
Je vois ces filles l'amour, et c'est la beauté essentielle
Été, profitez de l'histoire de l'air frais, l'humanité comment petite la poursuite du bonheur
« Yao Ming » à l'Assemblée mondiale de tir de robot, la louange valeur Yen moins la technologie thermique
Créer des problèmes - après la moitié Shen Congwen | recrutement Xi'an
Les pirates informatiques et programmeurs Quelle est la différence? L'objectif du programmeur est de devenir une divinité, le but des pirates est de tuer Dieu!
Tragique et de sang! 73 ans plus tard, ces anciens bâtiments rester vigilants chaque Wuhan
Jimmy montres en plus d'apprendre l'accent sur la sécurité de la carte, mais aussi pour aider les enfants à apprendre
Que ce soit le Real Madrid ou au Portugal, le meilleur partenaire quand il est C Lo!
Saint-Jean première nuit, est venu entre les montagnes et la poésie et le chant | sagesse · Grain in Festival Oreille Montagne Poésie
Alibaba architecte en chef à interroger: ces types de personnes, pas digne d'être un programmeur!
téléphone à écran pliant si cool 2019 téléphone mobile devrait être comme ça