JDK 1.2 zavádí nový rámec pro kolekce objektů s názvem Java Collections Framework. „Ach ne,“ zasténáte, „ani další API, ani jiný rámec, který byste se měli naučit!“ Ale počkejte, než se odvrátíte, vyslechněte mě: rámec kolekce stojí za vaši snahu a v mnoha ohledech bude přínosem pro vaše programování. Okamžitě vás napadnou tři velké výhody:
- Dramaticky zvyšuje čitelnost vašich sbírek tím, že poskytuje standardní sadu rozhraní pro použití mnoha programátory v mnoha aplikacích.
- Díky němu je váš kód flexibilnější tím, že umožňuje předávat a vracet rozhraní namísto konkrétních tříd, zobecňovat váš kód, místo aby jej uzamkl.
- Nabízí mnoho konkrétních implementací rozhraní, což vám umožňuje vybrat si nejvhodnější kolekci a nabízí nejvyšší výkon pro vaše potřeby.
A to je jen pro začátek.
Naše prohlídka rámce začne přehledem výhod, které poskytuje pro ukládání sad objektů. Jak brzy zjistíte, protože vaši starí přátelé z koně Hashtable
a Vektor
podporují nové API, vaše programy budou jednotné a stručné - něco, co vy a vývojáři přistupující k vašemu kódu určitě potěší.
Po naší předběžné diskusi se ponoříme hlouběji do podrobností.
Výhoda kolekce Java: Přehled
Předtím, než kolekce debutovala nejvíce, byly standardní metody pro seskupování objektů Java prostřednictvím pole, Vektor
a Hashtable
. Všechny tři tyto kolekce mají různé metody a syntaxi pro přístup k členům: pole používají symboly hranatých závorek ([]), Vektor
používá elementAt
metoda a Hashtable
používá dostat
a dát
metody. Tyto rozdíly dlouho vedly programátory k cestě k nekonzistenci při implementaci jejich vlastních sbírek - některé napodobují Vektor
přístupové metody a některé napodobují Výčet
rozhraní.
K dalšímu komplikování věci většina z Vektor
metody jsou označeny jako konečné; to znamená, že nemůžete rozšířit Vektor
třídy k implementaci podobného druhu kolekce. Mohli bychom vytvořit třídu kolekce, která vypadala jako Vektor
a choval se jako Vektor
, ale nemohlo to být předáno metodě, která trvá a Vektor
jako parametr.
Nakonec žádná ze sbírek (pole, Vektor
nebo Hashtable
) implementuje standardní rozhraní pro přístup členů. Když programátoři vyvinuli algoritmy (jako druhy) pro manipulaci s kolekcemi, vypukl vášnivý diskurs o tom, jaký objekt má být algoritmu předán. Pokud předáte pole nebo a Vektor
? Měli byste implementovat obě rozhraní? Mluvte o duplikaci a zmatku.
Naštěstí rámec Java Collections Framework tyto problémy napravuje a nabízí řadu výhod oproti tomu, že nepoužívá žádný rámec ani nepoužívá Vektor
a Hashtable
:
Použitelná sada sběrných rozhraní
Implementací jednoho ze základních rozhraní -
Sbírka
,Soubor
,Seznam
neboMapa
- zajistíte, aby vaše třída odpovídala společnému API a stala se pravidelnější a srozumitelnější. Takže ať už implementujete databázi SQL, porovnávač vzorníků barev nebo aplikaci pro vzdálený chat, pokud implementujeteSbírka
rozhraní, operace s vaší sbírkou objektů jsou vašim uživatelům dobře známy. Standardní rozhraní také zjednodušují předávání a vracení sbírek do a ze třídních metod a umožňují metodám pracovat na širší paletě sbírek.Základní sada implementací kolekce
Kromě důvěryhodných
Hashtable
aVektor
, které byly aktualizovány za účelem implementaceSbírka
rozhraní, byly přidány nové implementace kolekce, včetněHashSet
aSada stromů
,ArrayList
aSpojový seznam
, aHashMap
aMapa
. Použitím existující běžné implementace je váš kód kratší a rychlejší ke stažení. Také použití stávajícího jádra kódu Java Java zajišťuje, že jakákoli vylepšení základního kódu také zlepší výkon vašeho kódu.Další užitečná vylepšení
Každá kolekce nyní vrací
Iterátor
, vylepšený typVýčet
, který umožňuje operace prvků, jako je vkládání a mazání. TheIterátor
je „rychlé selhání“, což znamená, že dostanete výjimku, pokud seznam, který iterujete, změní jiný uživatel. Také kolekce založené na seznamu, jako jeVektor
vrátit aListIterator
které umožňují obousměrnou iteraci a aktualizaci.Několik sbírek (
Sada stromů
aTreeMap
) implicitně podporuje objednávání. Pomocí těchto tříd můžete snadno třídit seznam. Můžete najít nejmenší a největší prvky nebo provést binární vyhledávání, abyste zlepšili výkon velkých seznamů. Můžete třídit další kolekce poskytnutím metody porovnání kolekce (aKomparátor
objekt) nebo metoda porovnání objektu (Srovnatelný
rozhraní).Nakonec statická třída
Sbírky
poskytuje nemodifikovatelné (pouze pro čtení) a synchronizované verze existujících kolekcí. Nemodifikovatelné třídy jsou užitečné, aby se zabránilo nežádoucím změnám v kolekci. Synchronizovaná verze kolekce je pro programy s více vlákny nutností.
Rámec kolekce Java je součástí Core Java a je obsažen v java.util.collections
balíček JDK 1.2. Rámec je také k dispozici jako balíček pro JDK 1.1 (viz Zdroje).
Poznámka: Je pojmenována verze kolekcí JDK 1.1 com.sun.java.util.collections
. Mějte na paměti, že kód vyvinutý ve verzi 1.1 musí být aktualizován a znovu zkompilován pro 1.2 verson a všechny objekty serializované v 1.1 nelze deserializovat do 1.2.
Podívejme se nyní na tyto výhody podrobněji, když procvičíme rámec Java Collections Framework s nějakým naším vlastním kódem.
Dobré API
První výhodou Java Collections Framework je konzistentní a pravidelné API. API je kodifikováno v základní sadě rozhraní, Sbírka
, Soubor
, Seznam
nebo Mapa
. The Sbírka
rozhraní obsahuje základní operace sběru, jako je přidávání, odebírání a testy členství (zadržování). Jakákoli implementace kolekce, ať už je to ta, kterou poskytuje Java Collections Framework, nebo jedna z vašich vlastních výtvorů, bude podporovat jedno z těchto rozhraní. Protože framework kolekce je pravidelný a konzistentní, naučíte se velkou část rámců jednoduše tím, že se naučíte tato rozhraní.
Oba Soubor
a Seznam
implementovat Sbírka
rozhraní. The Soubor
rozhraní je totožné s Sbírka
rozhraní s výjimkou další metody, toArray
, který převádí a Soubor
do Objekt
pole. The Seznam
rozhraní také implementuje Sbírka
rozhraní, ale poskytuje mnoho přistupujících osob, které do seznamu používají celočíselný index. Například, dostat
, odstranit
, a soubor
všichni berou celé číslo, které ovlivňuje indexovaný prvek v seznamu. The Mapa
interface není odvozen ze sbírky, ale poskytuje rozhraní podobné metodám v java.util.Hashtable
. Klíče se používají k zadávání a získávání hodnot. Každé z těchto rozhraní je popsáno v následujících příkladech kódu.
Následující segment kódu ukazuje, jak provést mnoho Sbírka
operace na HashSet
, základní kolekce, která implementuje Soubor
rozhraní. A HashSet
je jednoduše sada, která neumožňuje duplicitní prvky a neobjednává ani neumisťuje své prvky. Kód ukazuje, jak vytvoříte základní kolekci a přidáte, odeberete a otestujete prvky. Protože Vektor
nyní podporuje Sbírka
můžete také spustit tento kód na vektoru, který můžete otestovat změnou HashSet
deklarace a konstruktor na Vektor
.
import java.util.collections. *; public class CollectionTest {// Statics public static void main (String [] args) {System.out.println ("Test kolekce"); // Vytvořit kolekci HashSet collection = new HashSet (); // Přidání řetězce dog1 = "Max", dog2 = "Bailey", dog3 = "Harriet"; collection.add (dog1); collection.add (dog2); collection.add (dog3); // Dimenzování System.out.println ("Sbírka vytvořena" + ", size =" + kolekce.size () + ", isEmpty =" + kolekce.isEmpty ()); // Containment System.out.println ("Sbírka obsahuje" + dog3 + ":" + collection.contains (dog3)); // Iterace. Iterátor podporuje hasNext, dále odstraňte System.out.println ("Kolekce iterace (bez řazení):"); Iterátor iterátor = collection.iterator (); while (iterator.hasNext ()) System.out.println ("" + iterator.next ()); // Odebrání collection.remove (dog1); collection.clear (); }}
Pojďme nyní stavět na našich základních znalostech sbírek a podívejme se na další rozhraní a implementace v rámci Java Collections Framework.
Dobré konkrétní implementace
Cvičili jsme Sbírka
rozhraní na konkrétní sbírce, HashSet
. Pojďme se nyní podívat na kompletní sadu implementací konkrétních kolekcí poskytovaných v rámci prostředí Java Collections. (V části Zdroje naleznete odkaz na anotovaný obrys rámce Java Collections společnosti Sun.)
Implementace | ||||||
---|---|---|---|---|---|---|
Tabulka hash | Nastavitelné pole | Vyvážený strom (seřazený) | Spojový seznam | Dědictví | ||
Rozhraní | Soubor | HashSet | * | Sada stromů | * | * |
Seznam | * | ArrayList | * | Spojový seznam | Vektor | |
Mapa | HashMap | * | TreeMap | * | Hashtable |
Implementace označené hvězdičkou (*) nedávají smysl nebo neposkytují žádný přesvědčivý důvod k implementaci. Například poskytnutí a Seznam
rozhraní k Hash tabulce nedává smysl, protože v Hash tabulce není pojem o pořadí. Podobně neexistuje Mapa
rozhraní pro propojený seznam, protože seznam nemá žádnou představu o vyhledání tabulky.
Pojďme nyní procvičovat Seznam
rozhraní tím, že pracuje na konkrétních implementacích, které implementují Seznam
rozhraní, ArrayList
a Spojový seznam
. Níže uvedený kód je podobný předchozímu příkladu, ale provádí mnoho Seznam
operace.
import java.util.collections. *; public class ListTest {// Statics public static void main (String [] args) {System.out.println ("List Test"); // Vytvořit kolekci ArrayList list = new ArrayList (); // Přidání řetězce [] toys = {"Shoe", "Ball", "Frisbee"}; list.addAll (Arrays.toList (hračky)); // Dimenzování System.out.println ("Seznam vytvořen" + ", size =" + list.size () + ", isEmpty =" + list.isEmpty ()); // Iterace pomocí indexů. System.out.println ("Seznam iterací (bez řazení):"); for (int i = 0; i <list.size (); i ++) System.out.println ("" + list.get (i)); // Zpětná iterace pomocí ListIterator System.out.println ("Seznam iterací (zpět):"); ListIterator iterator = list.listIterator (list.size ()); while (iterator.hasPrevious ()) System.out.println ("" + iterator.previous ()); // Odebrání list.remove (0); list.clear (); }}
Stejně jako v prvním příkladu je jednoduché vyměnit jednu implementaci za druhou. Můžete použít a Spojový seznam
místo ArrayList
jednoduše změnou řádku s ArrayList
konstruktor. Podobně můžete použít a Vektor
, který nyní podporuje Seznam
rozhraní.
Při rozhodování mezi těmito dvěma implementacemi byste měli zvážit, zda je seznam nestálý (často roste a zmenšuje se) a zda je přístup náhodný nebo uspořádaný. Moje vlastní testy ukázaly, že ArrayList
obecně překonává Spojový seznam
a nový Vektor
.
Všimněte si, jak přidáváme prvky do seznamu: používáme přidat vše
metoda a statická metoda Arrays.toList
. Tato statická metoda je jednou z nejužitečnějších metod obslužného programu v rámci kolekce, protože umožňuje zobrazit libovolné pole jako Seznam
. Nyní lze pole použít kdekoli a Sbírka
je potřeba.
Všimněte si, že procházím seznamem prostřednictvím indexovaného přístupového bodu, dostat
a ListIterator
třída. Kromě reverzní iterace ListIterator
Třída umožňuje přidat, odebrat a nastavit libovolný prvek v seznamu v bodě, na který se vztahuje ListIterator
. Tento přístup je docela užitečný pro filtrování nebo aktualizaci seznamu podle jednotlivých prvků.
Posledním základním rozhraním v prostředí Java Collections Framework je Mapa
. Toto rozhraní je implementováno dvěma novými konkrétními implementacemi, TreeMap
a HashMap
. The TreeMap
je vyvážená implementace stromu, která třídí prvky podle klíče.
Pojďme si ilustrovat použití Mapa
rozhraní s jednoduchým příkladem, který ukazuje, jak přidat, dotazovat a vymazat kolekci. Tento příklad, který používá HashMap
třída se příliš neliší od toho, jak jsme použili Hashtable
před debutem rámce sbírek. Nyní s aktualizací Hashtable
podporovat Mapa
rozhraní, můžete vyměnit řádek, který vytváří instanci HashMap
a nahradit jej instancí Hashtable
.