summaryrefslogtreecommitdiffstats
path: root/Master/Reference Architectures and Patterns/hjp5/html/k100098.html
blob: cf82890c532dcef5844dd22379a0803b3a11e7df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
<html>
<head>
<title>
Handbuch der Java-Programmierung, 5. Auflage
</title>
</head>
<body>
<a name="startofbody"></a>
<script language="JavaScript" src="hjp4lib.js">
</script>
<script language="JavaScript">
installKbdHandler("97,#startofbody;101,#endofbody;116,cover.html;122,k100003.html;115,search.html;105,index.html;100,JDKDOCS;112,APIDOCS;104,k100097.html;106,k100097.html;107,k100099.html;108,k100107.html");
</script>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html">&nbsp;Titel&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html">&nbsp;Inhalt&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html">&nbsp;Suchen&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html">&nbsp;Index&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()">&nbsp;DOC&nbsp;</a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100097.html">&nbsp;&lt;&lt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100097.html">&nbsp;&nbsp;&lt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100099.html">&nbsp;&nbsp;&gt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100107.html">&nbsp;&gt;&gt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()">&nbsp;API&nbsp;</a>
<td align="right">Kapitel 15 - Collections II
</table>
<hr>


<!-- Section -->
<a name="sectlevel2id015001"></a>
<h2>15.1 Grundlagen und Konzepte </h2>
<hr>
<ul>
<li><a href="k100098.html#sectlevel2id015001">15.1 Grundlagen und Konzepte</a>
</ul>
<hr>

<p>
Wie in <a href="k100090.html#kapitelcollections1">Kapitel 14</a> erl&auml;utert,
gibt es seit dem JDK 1.0 die &#187;traditionellen&#171; Collections
mit den Klassen <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>,
<a href="index_s.html#ixb100674"><font color=#000080><tt>Stack</tt></font></a>,
<a href="index_d.html#ixb100675"><font color=#000080><tt>Dictionary</tt></font></a>,
<a href="index_h.html#ixb100419"><font color=#000080><tt>Hashtable</tt></font></a>
und <a href="index_b.html#ixb100676"><font color=#000080><tt>BitSet</tt></font></a>.
Obwohl sie ihren Zweck durchaus erf&uuml;llen, gab es einige Kritik
am Collections-Konzept des JDK 1.0. Zun&auml;chst wurde die geringe
Vielseitigkeit kritisiert, etwa im Vergleich zum m&auml;chtigen Collection-Konzept
der Sprache SmallTalk. Zudem galten die JDK-1.0-Collections als nicht
sehr performant. Fast alle wichtigen Methoden sind <a name="ixa100919"><a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a></a>,
und als generische Speicher von Elementen des Typs <a href="index_o.html#ixb100224"><font color=#000080><tt>Object</tt></font></a>
ist bei jedem Zugriff ein Typecast bzw. eine Typ&uuml;berpr&uuml;fung
notwendig (wir kommen auf diese Begriffe in <a href="k100143.html#kapitelmultithreading">Kapitel 22</a>
zur&uuml;ck). Zudem gab es Detailschw&auml;chen, die immer wieder
kritisiert wurden. Als Beispiel kann die Wahl der Methodennamen des
<a href="index_e.html#ixb100122"><font color=#000080><tt>Enumeration</tt></font></a>-Interfaces
genannt werden. Oder die Implementierung der Klasse <a href="index_s.html#ixb100674"><font color=#000080><tt>Stack</tt></font></a>,
die als Ableitung von <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
weit &uuml;ber ihr eigentliches Ziel hinausschie&szlig;t. 

<p>
Diese Kritik wurde von den Java-Designern zum Anla&szlig; genommen,
das Collection-Konzept im Rahmen der Version 1.2 neu zu &uuml;berdenken.
Herausgekommen ist dabei eine Sammlung von gut 20 Klassen und Interfaces
im Paket <a name="ixa100920"><a href="index_j.html#ixb100127"><font color=#000080><tt>java.util</tt></font></a></a>,
die das Collections-Framework des JDK 1.2 bilden. Wer bei dieser Zahl
erschreckt, sei getr&ouml;stet. Letztlich werden im wesentlichen die
drei Grundformen <a name="ixa100921"><a href="index_s.html#ixb100716"><font color=#000080><tt>Set</tt></font></a></a>,
<a name="ixa100922"><a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a></a>
und <a name="ixa100923"><a href="index_m.html#ixb100718"><font color=#000080><tt>Map</tt></font></a></a>
realisiert. Die gro&szlig;e Anzahl ergibt sich aus der Bereitstellung
verschiedender Implementierungsvarianten, Interfaces und einiger abstrakter
Basisklassen, mit denen die Implementierung eigener Collections vereinfacht
werden kann. Wir wollen uns zun&auml;chst mit der grundlegenden Arbeitsweise
der Collection-Typen vertraut machen: 
<ul>
<li>Eine <a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a>
ist eine beliebig gro&szlig;e Liste von Elementen beliebigen Typs,
auf die sowohl wahlfrei als auch sequenziell zugegriffen werden kann.
<li>Ein <a href="index_s.html#ixb100716"><font color=#000080><tt>Set</tt></font></a>
ist eine (doublettenlose) Menge von Elementen, auf die mit typischen
Mengenoperationen zugegriffen werden kann.
<li>Eine <a href="index_m.html#ixb100718"><font color=#000080><tt>Map</tt></font></a>
ist eine Abbildung von Elementen eines Typs auf Elemente eines anderen
Typs, also eine Menge zusammengeh&ouml;riger Paare von Objekten.
</ul>

<p>
Jede dieser Grundformen ist als Interface unter dem oben angegebenen
Namen implementiert. Zudem gibt es jeweils eine oder mehrere konkrete
Implementierungen. Sie unterscheiden sich in den verwendeten Datenstrukturen
und Algorithmen und damit in ihrer Eignung f&uuml;r verschiedene Anwendungsf&auml;lle.
Weiterhin gibt es eine abstrakte Implementierung des Interfaces, mit
dessen Hilfe das Erstellen eigener Collections erleichtert wird. 
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100%>
<tr>
<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=1></td>
<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top width=1000>

<p>
Im Gegensatz zu den 1.1-Klassen sind die Collections des JDK 1.2 aus
Performancegr&uuml;nden durchg&auml;ngig unsynchronisiert. Soll also
von mehr als einem Thread gleichzeitig auf eine Collection zugegriffen
werden (Collections sind h&auml;ufig Kommunikationsmittel zwischen
gekoppelten Threads), so ist unbedingt darauf zu achten, die Zugriffe
selbst zu synchronisieren. Andernfalls k&ouml;nnen leicht Programmfehler
und Dateninkonsistenzen entstehen. Wie Sie den Zugriff auf die Klassen
des Collection Frameworks synchronisieren erfahren Sie in <a href="k100104.html#subsectionsynccollections">Abschnitt 15.7.2</a>.</td>
<td><img src="trp1_1.gif" width=2></td>
<td valign=top>
<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#FF9900">
<tr>
<td><font color="#FFFFFF">&nbsp;JDK1.1-6.0&nbsp;</font></td>
</tr>
</table>
</td>
<td width=1 align=left valign=top bgcolor="#FF9900"><img src="trp1_1.gif"></td>
</tr>
</table>

<p>
Die Namensgebung der Interfaces und Klassen folgt einem einfachen
Schema. Das Interface hat immer den allgemein verwendeten Namen der
zu implementierenden Collection, also beispielsweise <a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a>,
<a href="index_s.html#ixb100716"><font color=#000080><tt>Set</tt></font></a>
oder <a href="index_m.html#ixb100718"><font color=#000080><tt>Map</tt></font></a>.
Jede Implementierungsvariante stellt vor den Namen dann eine spezifische
Bezeichnung, die einen Hinweis auf die Art der verwendeten Datenstrukturen
und Algorithmen geben soll. So gibt es f&uuml;r das Interface <a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a>
beispielsweise die Implementierungsvarianten <a name="ixa100924"><a href="index_l.html#ixb100695"><font color=#000080><tt>LinkedList</tt></font></a></a>
und <a name="ixa100925"><a href="index_a.html#ixb100719"><font color=#000080><tt>ArrayList</tt></font></a></a>
sowie die abstrakte Implementierung <a name="ixa100926"><a href="index_a.html#ixb100720"><font color=#000080><tt>AbstractList</tt></font></a></a>.
Wenn man dieses Schema einmal begriffen hat, verliert der &#187;Collection-Zoo&#171;
viel von seinem Schrecken. 

<p>
Die Interfaces spielen eine wichtige Rolle, denn sie beschreiben bereits
recht detailliert die Eigenschaften der folgenden Implementierungen.
Dabei wurde im JDK 1.2 eine weitreichende Design-Entscheidung getroffen.
Um nicht f&uuml;r jede denkbare Collection-Klasse ein eigenes Interface
definieren zu m&uuml;ssen, wurde ein Basisinterface <a name="ixa100927"><a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a></a>
geschaffen, aus dem die meisten Interfaces abgeleitet wurden. Es fasst
die wesentlichen Eigenschaften einer gro&szlig;en Menge unterschiedlicher
Collections zusammen: 
<p>
<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#EEFFCC">
<tr>
<td valign=top width=100%>
<font color="#660066">
<pre>
int size()
boolean isEmpty()
boolean contains(Object o)
Iterator iterator()
Object[] toArray()
Object[] toArray(Object[] a)
boolean add(Object o)
boolean remove(Object o)
boolean containsAll(Collection c)
boolean addAll(Collection c)
boolean removeAll(Collection c)
boolean retainAll(Collection c)
void clear()
boolean equals(Object o)
int hashCode()
</pre>
</font>
</td>
<td valign=top>
<a href="../jdkdocs/api/java/util/Collection.html" onClick="this.href=getApiDoc('java.util.Collection')"><font color="#660066" size=-1>java.util.Collection</font></a></td>
</tr>
</table>

<p>
Zus&auml;tzlich fordert die JDK-1.2-Spezifikation f&uuml;r jede Collection-Klasse
zwei Konstruktoren (was ja leider nicht im Rahmen der Interface-Definition
sichergestellt werden kann). Ein parameterloser Konstruktor wird verwendet,
um eine leere Collection anzulegen. Ein weiterer, der ein einzelnes
<a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a>-Argument
besitzt, dient dazu, eine neue Collection anzulegen und mit allen
Elementen aus der als Argument &uuml;bergebenen Collection zu f&uuml;llen.
Die Interfaces <a href="index_l.html#ixb100717"><font color=#000080><tt>List</tt></font></a>
und <a href="index_s.html#ixb100716"><font color=#000080><tt>Set</tt></font></a>
sind direkt aus <a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a>
abgeleitet, <a name="ixa100928"><a href="index_s.html#ixb100722"><font color=#000080><tt>SortedSet</tt></font></a></a>
entstammt ihr (als Nachfolger von <a href="index_s.html#ixb100716"><font color=#000080><tt>Set</tt></font></a>)
mittelbar. Lediglich die Interfaces <a href="index_m.html#ixb100718"><font color=#000080><tt>Map</tt></font></a>
und das daraus abgeleitete Interface <a name="ixa100929"><a href="index_s.html#ixb100723"><font color=#000080><tt>SortedMap</tt></font></a></a>
wurden nicht aus <a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a>
abgeleitet. 

<p>
Der Vorteil dieses Designs ist nat&uuml;rlich, dass eine flexible
Schnittstelle f&uuml;r den Umgang mit <i>Mengen von Objekten</i> zur
Verf&uuml;gung steht. Wenn eine Methode einen R&uuml;ckgabewert vom
Typ <a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a>
besitzt, k&ouml;nnen die Aufrufer dieser Methode auf die zur&uuml;ckgegebenen
Elemente - unabh&auml;ngig vom Typ der tats&auml;chlich zur&uuml;ckgegebenen
Collection-Klasse - einheitlich zugreifen. Selbst wenn eine andere
<i>Implementierung</i> gew&auml;hlt wird, &auml;ndert sich f&uuml;r
den Aufrufer nichts, solange das zur&uuml;ckgegebene Objekt das <a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a>-Interface
implementiert. 

<p>
Soweit zur Theorie. Der designerische Nachteil dieses Ansatzes besteht
darin, dass l&auml;ngst nicht alle tats&auml;chlichen Collections
eine Schnittstelle besitzen, wie sie in <a href="index_c.html#ixb100721"><font color=#000080><tt>Collection</tt></font></a>
definiert wurde. W&auml;hrend diese f&uuml;r eine Liste noch passen
mag, besitzt eine Queue oder ein Stack g&auml;nzlich anders arbeitende
Zugriffsroutinen. Dieser Konflikt wurde dadurch zu l&ouml;sen versucht,
dass die Methoden <i>zum &Auml;ndern</i> der Collection <i>optional</i>
sind. W&auml;hrend also <a name="ixa100930"><a href="index_c.html#ixb100700"><font color=#000080><tt>contains</tt></font></a></a>,
<a name="ixa100931"><a href="index_c.html#ixb100724"><font color=#000080><tt>containsAll</tt></font></a></a>,
<a href="index_e.html#ixb100223"><font color=#000080><tt>equals</tt></font></a>,
<a name="ixa100932"><a href="index_h.html#ixb100418"><font color=#000080><tt>hashCode</tt></font></a></a>,
<a name="ixa100933"><a href="index_i.html#ixb100678"><font color=#000080><tt>isEmpty</tt></font></a></a>,
<a name="ixa100934"><a href="index_s.html#ixb100679"><font color=#000080><tt>size</tt></font></a></a>
und <a name="ixa100935"><a href="index_t.html#ixb100725"><font color=#000080><tt>toArray</tt></font></a></a>
obligatorisch sind, m&uuml;ssen die &uuml;brigen Methoden in einer
konkreten Implementierung nicht unbedingt zur Verf&uuml;gung gestellt
werden, sondern k&ouml;nnen weggelassen, ersetzt oder erg&auml;nzt
werden. 

<p>
Aus <a href="k100057.html#kapiteloop3">Kapitel 9</a> wissen wir allerdings,
dass <i>alle</i> definierten Methoden eines Interfaces in einer konkreten
Implementierung zur Verf&uuml;gung gestellt werden m&uuml;ssen. Davon
sind nat&uuml;rlich auch die Collection-Klassen nicht ausgenommen.
Wenn sich diese entschlie&szlig;en, eine optionale Methode nicht zu
realisieren, so muss diese zwar implementiert werden, l&ouml;st aber
beim Aufruf eine Exception des Typs <a name="ixa100936"><a href="index_u.html#ixb100726"><font color=#000080><tt>UnsupportedOperationException</tt></font></a></a>
aus. Die tats&auml;chliche Schnittstelle einer konkreten Collection-Klasse
kann also nicht dem Interface entnommen werden, das sie implementiert,
sondern erfordert zus&auml;tzlich die schriftliche Dokumentation der
Klasse. 

<p>
&Uuml;ber diesen Designansatz kann man sich streiten. Da sowieso nur
die nicht-ver&auml;ndernden Methoden nicht-optional sind, h&auml;tte
man ebenso gut diese allein in ein generisches Collection-Interface
stecken k&ouml;nnen und von allen Collection-Klassen implementieren
lassen k&ouml;nnen. Zus&auml;tzliche Methoden w&auml;ren dann in abgeleiteten
Interfaces passend zur jeweiligen Collection-Klasse zu definieren.
<hr>
<table border=0 cellpadding=0 cellspacing=1 width="100%">
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="cover.html">&nbsp;Titel&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html">&nbsp;Inhalt&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html">&nbsp;Suchen&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html">&nbsp;Index&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()">&nbsp;DOC&nbsp;</a>
<td align="right">Handbuch der Java-Programmierung, 5. Auflage, Addison
Wesley, Version 5.0.1
<tr bgcolor="#EEFFCC">
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100097.html">&nbsp;&lt;&lt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100097.html">&nbsp;&nbsp;&lt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100099.html">&nbsp;&nbsp;&gt;&nbsp;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="k100107.html">&nbsp;&gt;&gt;&nbsp;</a>
<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()">&nbsp;API&nbsp;</a>
<td align="right">&copy; 1998, 2007 Guido Kr&uuml;ger &amp; Thomas
Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
</table>
<a name="endofbody"></a>
</body>
</html>