Porovnanie HashSet a TreeSet

1. Úvod

V tomto článku budeme porovnávať dve z najpopulárnejších implementácií Java z java.util.Set rozhranie - HashSet a TreeSet.

2. Rozdiely

HashSet a TreeSet sú listy tej istej vetvy, ale líšia sa v niekoľkých dôležitých veciach.

2.1. Objednávanie

HashSet ukladá objekty v náhodnom poradí, zatiaľ čo TreeSet použije prirodzené poradie prvkov. Pozrime sa na nasledujúci príklad:

@Test public void givenTreeSet_whenRetrievesObjects_thenNaturalOrder () {Set set = new TreeSet (); set.add ("Baeldung"); set.add ("je"); set.add ("Úžasné"); assertEquals (3, set.size ()); assertTrue (set.iterator (). next (). equals ("Awesome")); }

Po pridaní String predmety do TreeSet, vidíme, že prvý je „úžasný“, aj keď bol pridaný úplne na konci. Podobná operácia sa vykonala s HashSet nezaručuje, že poradie prvkov zostane v priebehu času konštantné.

2.2. Nulový Predmety

Ďalším rozdielom je to HashSet môže skladovať nulový predmety, zatiaľ čo TreeSet neumožňuje im:

@Test (očakáva sa = NullPointerException.class) public void givenTreeSet_whenAddNullObject_thenNullPointer () {Set set = new TreeSet (); set.add ("Baeldung"); set.add ("je"); set.add (null); } @Test public void givenHashSet_whenAddNullObject_thenOK () {Set set = new HashSet (); set.add ("Baeldung"); set.add ("je"); set.add (null); assertEquals (3, set.size ()); }

Ak sa pokúsime uložiť nulový objekt v a TreeSet, bude výsledkom operácie vyhodenie NullPointerException. Jedinou výnimkou bola Java 7, keď bolo dovolené mať presne jednu nulový prvok v TreeSet.

2.3. Výkon

Jednoducho povedané, HashSet je rýchlejší ako TreeSet.

HashSet poskytuje výkon v konštantnom čase pre väčšinu operácií ako pridať (), odstrániť () a obsahuje (), oproti log(n) čas ponúkaný TreeSet.

Spravidla to vidíme čas vykonania pridania prvkov do TreeSet je oveľa lepší ako pre HashSet.

Pamätajte, že JVM sa nemusí zahriať, takže časy vykonania sa môžu líšiť. Dobrá diskusia o tom, ako navrhnúť a vykonať mikro testy pomocou rôznych nástrojov Nastaviť implementácie je k dispozícii tu.

2.4. Implementované metódy

TreeSet je bohatý na funkčnosť, implementácia ďalších metód ako:

  • pollFirst () - vrátiť prvý prvok alebo - nulový ak Nastaviť je prázdny
  • pollLast () - načítať a odstraňovať posledný prvok alebo sa vrátiť nulový ak Nastaviť je prázdny
  • najprv() - vrátiť prvú položku
  • posledný ()vrátiť poslednú položku
  • strop () - vrátiť najmenší prvok väčší alebo rovný danému prvku, alebo nulový ak taký prvok neexistuje
  • nižší () - vrátiť najväčší prvok striktne menej ako daný prvok, alebo nulový ak taký prvok neexistuje

Vyššie uvedené metódy robia TreeSet oveľa jednoduchšie na použitie a výkonnejšie ako HashSet.

3. Podobnosti

3.1. Jedinečné prvky

Oboje TreeSet a HashSet záruka a bezduplikátny zber prvkov, keďže je súčasťou všeobecného Nastaviť rozhranie:

@Test public void givenHashSetAndTreeSet_whenAddDuplicates_thenOnlyUnique () {Set set = new HashSet (); set.add ("Baeldung"); set.add ("Baeldung"); assertTrue (set.size () == 1); Set set2 = new TreeSet (); set2.add ("Baeldung"); set2.add ("Baeldung"); assertTrue (set2.size () == 1); }

3.2. Nie synchronizované

Žiadny z opísaných Nastaviť implementácie sú synchronizované. To znamená, že ak má viac vlákien prístup k a Nastaviť súčasne a najmenej jedno z vlákien ho upravuje, potom musí byť externe synchronizované.

3.3. Iterátory rýchle zlyhania

The Iterátors vrátené používateľom TreeSet a HashSet sú rýchle.

To znamená, že akákoľvek zmena Nastaviť kedykoľvek po Iterátor je vytvorený bude hádzať a ConcurrentModificationException:

@Test (očakáva sa = ConcurrentModificationException.class) public void givenHashSet_whenModifyWhenIterator_thenFailFast () {Set set = new HashSet (); set.add ("Baeldung"); Iterátor it = set.iterator (); while (it.hasNext ()) {set.add ("Úžasné"); it.next (); }}

4. Akú implementáciu použiť?

Obe implementácie plnia kontrakt myšlienky sady, takže je na kontexte, ktorú implementáciu môžeme použiť.

Tu je niekoľko rýchlych bodov na zapamätanie:

  • Ak chceme, aby boli naše záznamy zoradené, musíme ísť na TreeSet
  • Ak si vážime výkon viac ako spotrebu pamäte, mali by sme ísť na HashSet
  • Ak máme nedostatok pamäti, mali by sme ísť na TreeSet
  • Ak chceme získať prístup k prvkom, ktoré sú relatívne blízko seba podľa ich prirodzeného usporiadania, možno by sme mali zvážiť TreeSet pretože má väčšiu lokalitu
  • HashSetVýkon je možné vyladiť pomocou initialCapacity a vyťaženosť, čo nie je možné pre TreeSet
  • Ak chceme zachovať poradie vloženia a ťažiť z neustáleho prístupu v čase, môžeme použiť LinkedHashSet

5. Záver

V tomto článku sme sa venovali rozdielom a podobnostiam medzi TreeSet a HashSet.

Príklady kódov pre tento článok sú ako vždy dostupné na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found