Hogyan működik a Dictionary?

A minap feltettek nekem néhány kérdést a .NET működésével/használatával kapcsolatban. A legtöbbre rögtön tudtam a választ (legfeljebb egy kicsit nehéz volt angolul, ábrák felrajzolása nélkül kifejteni, hogy mik is az érték- és referencia-szerinti paraméterátadás nüansznyi, de ordas nagy hibalehetőségeket hordozó különbségei érték- és referenciatípusok esetén 🙂 ), de egy kérdés kicsit leizzasztott. Körülbelül így szólt: átlagosan mennyi idő – hány művelet elvégzése – alatt tárol el egy adatot egy hashtábla?

Mindezt ugye Ordoban (Ο – én most az omikront használom helyette, amíg meg nem találom a kódját) megadva.

A fenti szimbólumot iskolában/munkában kb. 6-7 éve láttam utoljára, úgyhogy a testhőmérsékletem pillanatok alatt a 310 Kelvint kezdte súrolni, és amennyire éreztem, a pulzusom is 3 digitesre nőtt. 🙂 De elővettem a .NET-es tudásomat a Dictionaryről – amit úgy háromhavonta le is kell oktatnom -, és nekiálltam levezetni, hogy mennyi is lehet az annyi.

Hogyan működik egy Dictionary?

(Tekintve, hogy a Hashtable egy típusbizonytalan osztály, inkább a .NET 2.0-ban megjelent utódján, a Dictionary<K,V>-n magyarázok.)

A Dictionary kulcs-érték párokat tárol. Amikor hozzáadunk egy új párt, a kulcs alapján valahogy elhelyezi az adatot a memóriában. Amikor kíváncsiak vagyunk egy értékre, akkor a kulcs alapján kereshetünk rá; vagyis megadunk egy kulcsot, és ha az szerepel a szótárban, akkor valahogy előkeresi, és visszaadja a hozzárendelt értéket. Ha nem szerepel, akkor kapunk egy KeyNotFoundExceptiont. Ha egy olyan kulcsot próbálunk hozzáadni a szótárhoz, ami már szerepel benne, akkor a szótár ezt valahogy megérzi. 🙂 Dob egy kivételt, mert egy kulcs csak egyszer szerepelhet. Eddig valószínűleg mindenkinek ismerős.

A lényeg, hogy ez a sok valahogy mit is takar pontosan. Hogyan helyezi el az adatot a memóriában? Hogyan keresi elő? Mi alapján mondja meg, hogy két kulcs megegyezik?

Kezdetnek álljon itt egy példa és némi kód, hogy legyen min prezentálni.

2390-ben a UFP épp elnököt választana. A különböző bolygók jelöltjeit egy szótárban gyűjtik össze. (Életszerű szituáció.)

Legyen tehát egybolygó osztályunk; tartalmazza a bolygó nevét és lakosságát.

public class Planet
{
    public string Name { get; set; }
    public int Population { get; set; } //billion people
}

Hozzunk létre egy szótárat, és adjunk hozzá néhány bolygót. A szótárban a kulcs a bolygó lesz, a hozzá rendelt érték pedig a jelölt neve. Tegyük fel, hogy az adatok egyenként érkeznek be, a rendszer nem valós bolygó objektumokra vár referenciát, hanem a jelölt maga adhatja meg az őt jelölő bolygó adatait.


Dictionary<Planet, string> candidates = new Dictionary<Planet, string>();

Console.WriteLine("Adding Picard of Earth...");
candidates.Add(new Planet
    { Name = "Earth", Population = 9 }, "Jean-Luc Picard");
Console.WriteLine("Adding Brex of Bolarus IX...");
candidates.Add(new Planet
    { Name = "Bolarus IX", Population = 8 }, "Solian Jarso Brex");
Console.WriteLine("Adding Dax of Trill...");
candidates.Add(new Planet
    { Name = "Trill", Population = 9 }, "Ezri Dax");
Console.WriteLine("Adding Khan of Earth...");
candidates.Add(new Planet
    { Name = "Earth", Population = 9 }, "Khan Noonien Singh");

No, ezzel megvolnánk. A probléma csak annyi, hogy ez így le is fut, márpedig Khan csalni akar: ugyanazt a bolygót mondja hazájának, mint Picard. Mivel két különböző objektumról van szó (hiszen mindkét jelölt saját maga készített egy Planet példányt az Add metódus meghvásakor), a Dictionary különböző objektumnak látja őket, tehát engedni fogja, hogy a Földnek két jelöltje legyen. Ezt a galádságot csakis a Flotta .NET-programozói előzhetik meg! 🙂

Hogyan vizsgálja a Dictionary a kulcsegyezőséget?

A Dictionary az egyes kulcsok két metódusát használja a kulcsegyezőség felderítésére: A GetHashCode-ot, illetve az Equalst. Mindkettő a System.Objecten definiált, tehát az égegyadtavilágon minden objektum megörökli.

Amikor egy kulcsnak megpróbál helyet találni, a szótár meghívja a kulcs GetHashCode metódusát. Ez a metódus egy integert ad vissza – ha nem override-oltuk, akkor a keretrendszer egy – az AppDomainben legalábbis – egyedi számot ad vissza, tehát minden objektum más és más hashsel fog rendelkezni. Ha felülírjuk, akkor nekünk kell valamilyen úton-módon egy hash-értéket kiszámolni az objektumunkból. (Eme érték kiszámolásának szabályairól, buktatóiról majd egy későbbi postban írok.)

Ez eddig szép, de mire jó? Eltárolja egy listában a hasht, és mellette az értéket? Korántsem.

Hogyan tárolja el a Dictionary az elemeket?

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English

A kapott hashből a Dictionary el tudja helyezni az elemet a magában tárolt tömb egyik helyére. Vagyis egy objektum hashkódja és a tárolási memóriacím között tulajdonképpen egyértelmű leképezés van…. elvileg. Tökéletes hash-algoritmus használata esetén. Egyelőre ezt még a Borg is keresi.

Tehát: mind az elhelyezés, mind a későbbi visszakeresés átlagosan Ο(1) lépés alatt végbemegy – csak le kell kérdezni, és át kell transzformálni a hasht egy tömbindexre. Valójában a lentebb részletezett okok miatt ez nem 1, hanem mondjuk 1+x, de mindenképpen kicsi és konstans.

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English

Ellenpéldának ott van mondjuk egy elem beszúrása egy tömbbe, aztán előkeresése: beszúrni Ο(n), hiszen legrosszabb esetben – vagyis ha a tömb első helyére akarunk beszúrni -, n db lépésbe kerül shiftelni a tömböt. Keresésnél szintén O(n) lépés lehet a dolog, hiszen végig kell mászni a tömbön, hogy megtaláljuk a keresett elemet. Egy szótárnál az elem helyét azonnal megadja a hashcode átalakítása.

Kössünk bele a vizsgálatba!

Ennyi magyarázat után akkor most lássunk munkához! Írjuk felül a GetHashCode-ot a Planet osztályban.

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
public override int GetHashCode()
{
    Console.WriteLine("\tGetHashCode called on " + Name);
    return Name.Length * Population;
}
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English

Az első sor természetesen nem szükséges, csak azért szúrtuk be, hogy amíg teszteljük a működést, lássuk, mikor hívódik a metódus. A második sor a lényeg: fogjuk a bolygó nevének hosszát, és összeszorozzuk a lakossággal. Ez elvileg már ad némi differenciát az egyes bolygók hashe között – ugyanis az a jó algoritmus, ami az értékkészleten jól szétoszlik.

(Megj.: simán az is elég lett volna, ha a Name.GetHashCode()-ot adjuk vissza, de egyszerűen nincs szívem ennyire suta “algoritmust” gyártani. 🙂 )

Próbáljuk ki… az eredmény talán meglepő: még mindig lefut a program.

Az egyezőségvizsgálat második fele

Ez azért történik, mert ha a Dictionary két azonos hasht észlel (vagyis észreveszi, hogy az adott cím már foglalt a tömbben), akkor meghívja az eltárolt elem kulcsának Equals metódusát, és átadja ennek az új kulcsot. A feladat tehát adott, írjuk felül az Equalst is!

public override bool Equals(object obj)
{
    Console.WriteLine("\tEquals called on " + Name);
    Planet other = obj as Planet;
    if (other != null && Name == other.Name)
        return true;
    return false;
}

Innentől megy is minden. Vagyis épp ellenkezőleg: kivételt kapunk, amikor Khan megpróbál csalni, de pont ez volt a célunk.

Lássuk, mit főztünk!

Érdemes belenéznünk a futás eredményébe:

 Adding Picard of Earth...
     GetHashCode called on Earth
 Adding Brex of Bolarus IX...
     GetHashCode called on Bolarus IX
 Adding Dax of Trill...
     GetHashCode called on Trill
     Equals called on Earth
 Adding Khan of Earth...
     GetHashCode called on Earth
     Equals called on Trill
     Equals called on Earth

…ééés ArgumentException.

Ebből látszik, hogy minden egyes elem hozzáadásakor hívódik a GetHashCode: a Dictionary meghatározza a tárolás helyét.

Ami érdekes, hogy az Equals nem csak Khannál hívódik, hanem már Daxnál is! Nem véletlenül: a “Trill”.Length * 9 éppen annyi, mint az “Earth”.Length * 9, tehát az algoritmusunk ugyanazt a hasht számolta ki mindkét elemre. Ekkor a szótár meghívja az Equalst a már meglévő kulcson (Picard Earth objektuma), amely közli, hogy nincs gond, az új kulcs nem azonos a régivel.

Node akkor van egy kis gond. Két kulcs adta ugyanazt a hasht, de az Equals szerint ezek a kulcsok különbözőek, tehát szerepelhetnek egyszerre a szótárban.   Ugyanabba a “cellába” kellene rakni két elemet. Ilyenkor mi történik?

Két azonos hash-ű, de különböző kulcs esete

A Dictionary éppen amiatt, mert nem lehet tökéletes hash-algoritmust találni minden típusra, logikailag nem csak hash-elem párokban gondolkodik, hanem minden hash-hez kezelni tud egy “vödröt”. Ha két azonos hash-ű, de különböző kulcsot kell tárolnia, akkor kénytelen ugyanabba a “vödörbe” helyezni az új elemet, mint amiben a régi van.

Vagyis innentől, ha egy olyan elemet próbálunk kivenni, amelynek kulcsa a fenti két bolygó egyike, akkor több lépés lesz megtalálni az elemet, mert nem elég a hash alapján kiválasztani a helyet: még végig kell menni a vödörben lévő elemeken, amíg meg nem találjuk a keresettet. Tehát egy rossz hashelési algoritmus leronthatja a Dictionary teljesítményét – de nagy elemszámnál még így is jóval gyorsabb lesz egy hashtábla, mint egy tömb.

A Trill jelölt hozzáadása utáni lépésnél már világos, hogy mi történik. A Dictionary megkapja a hasht Khan bolygójától. Észreveszi, hogy az a hash már foglalt: összehasonlítja az összes egyező hashű elemmel ezt az új kulcsot. Meghívja az Equalst a korábbi Trill, illetve Earth objektumon. Utóbbi true-t ad vissza – ekkor a Dictionary dob egy kivételt, mert a kulcs már szerepel.

Hogyan történik a keresés?

Csak, hogy megbizonyosodjunk az eddigiek helyességéről, írjunk be néhány sor plusz kódot a Main metódusunkba, a korábbiak mögé. (Természetesen kommentezzük/töröljük a Khanos sort, ami kivételt dob!)


Console.WriteLine("---Reading the name of the candidate from Trill---");
Console.WriteLine(candidates[new Planet
    { Name = "Trill", Population = 9 }]);

Console.WriteLine("---Reading the name of the candidate from Earth---");
Console.WriteLine(candidates[new Planet
    { Name = "Earth", Population = 9 }]);

Világos, mit szeretnénk: előhúzni két elemet a kalapból, méghozzá pont azokat, akikről tudjuk, hogy ugyanaz a hashük. Az eredmény az lesz, amit várunk: kapunk egy hash-vizsgálatot (a kulcson), majd amikor ebből meghatározta az elem tömbbéli indexét, jön a vödör elemein való végiglépkedés, Equals-hívás, amíg meg nem találja az azonos kulcsú elemet.

Összegezve, röviden

A hashtáblák, így a Dictionary<K, V> működésének alapja, hogy a beléjük helyezett elempárok kulcs részét egy függvény segítségével egy integerré alakítják, amely integer megadja, hogy a hashtábla mögötti tömb mely helyére kell beilleszteni az adott kulcs-érték párt. (A .NET-ben ez a függvény rendszerszinten része minden objektumnak, de ahogy fentebb is láttuk, saját típusnál könnyen lecserélhető.) Ennek köszönhetően mind az elem hozzáadása, mind a megkeresése egyetlen lépésben megoldható.

Abban az esetben, ha elérjük a hash függvény korlátait, vagyis két különböző elem ugyanazt a hasht adja vissza, a hashtábla egy láncolt listát hoz létre az adott elemhez, mely listában eltárolja az összes adott hash-ű kulcs-érték párt. (Tudtommal a Dictionary a list heades chaininget implementálja, de akárhogy kutatok, erről nem találok infót. Ha nem így lenne, javítsatok ki!) A beszúrás/keresés ideje ilyenkor néhány lépéssel megnő, de a legrosszabb kivételével  (amikor minden elemnek ugyanaz a hash-e) minden esetben alacsonyabb lesz, mint egy tömbnél lenne.

További okosságok

Lenne még miről írni. Bőven. Fogok is, ha legyőztem a WorkItemek hadseregét. 🙂 Ott van például az, hogy mire kell ügyelni egy saját hash-algoritmus írása esetén. (Másképpen fogalmazva: miért ne használj soha olyan hash-algót, amit fentebb írtunk a Planet osztályhoz. :D) Vagy, hogy hogyan tudunk az elemek összehasonlításába beleszólni, ha nem saját típusúak az elemek, vagyis nem tudjuk felülcsapni a göthöskód és ikvolsz metódusokat. Vagy, hogy mi az a load factor, mit tudunk befolyásolni vele. Illetve, talán érdemes lesz megvizsgálni a Dictionary<K,V> konkrét megvalósítását is, metódusok szintjén.

Mára azonban legyen elég ennyi. Remélem, segített valakinek a fenti sok-sok ujjkoptatás. 🙂

Hihetetlen, de szombat éjjel is csak azzal tudom zárni a postot, hogy…

…és most vissza kódolni.

AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
AfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDetect languageDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddishAfrikaansAlbanianArabicArmenianAzerbaijaniBasqueBelarusianBulgarianCatalanChinese (Simplified)Chinese (Traditional)CroatianCzechDanishDutchEnglishEstonianFilipinoFinnishFrenchGalicianGeorgianGermanGreekHaitian CreoleHebrewHindiHungarianIcelandicIndonesianIrishItalianJapaneseKoreanLatinLatvianLithuanianMacedonianMalayMalteseNorwegianPersianPolishPortugueseRomanianRussianSerbianSlovakSlovenianSpanishSwahiliSwedishThaiTurkishUkrainianUrduVietnameseWelshYiddish

English (auto-detected) » English
Advertisements

~ Szerző: Fülöp Dávid - 2011. április 16..

Egy hozzászólás to “Hogyan működik a Dictionary?”

  1. […] A Dictionary mögött levő algoritmus például ekkor hívja az Equals() függvényt, mint ahogy ebben a cikkben nagyszerűen le van […]

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s

 
%d blogger ezt kedveli: