summaryrefslogtreecommitdiffstats
path: root/Master/Reference Architectures and Patterns/hjp5/html/k100314.html
diff options
context:
space:
mode:
authorSven Eisenhauer <sven@sven-eisenhauer.net>2023-11-10 15:11:48 +0100
committerSven Eisenhauer <sven@sven-eisenhauer.net>2023-11-10 15:11:48 +0100
commit33613a85afc4b1481367fbe92a17ee59c240250b (patch)
tree670b842326116b376b505ec2263878912fca97e2 /Master/Reference Architectures and Patterns/hjp5/html/k100314.html
downloadStudium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.gz
Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.bz2
add new repoHEADmaster
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100314.html')
-rw-r--r--Master/Reference Architectures and Patterns/hjp5/html/k100314.html1055
1 files changed, 1055 insertions, 0 deletions
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100314.html b/Master/Reference Architectures and Patterns/hjp5/html/k100314.html
new file mode 100644
index 0000000..d8b5965
--- /dev/null
+++ b/Master/Reference Architectures and Patterns/hjp5/html/k100314.html
@@ -0,0 +1,1055 @@
+<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,k100312.html;106,k100313.html;107,k100315.html;108,k100317.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="k100312.html">&nbsp;&lt;&lt;&nbsp;</a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100313.html">&nbsp;&nbsp;&lt;&nbsp;&nbsp;</a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100315.html">&nbsp;&nbsp;&gt;&nbsp;&nbsp;</a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100317.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 50 - Performance-Tuning
+</table>
+<hr>
+
+
+<!-- Section -->
+<a name="sectlevel2id050002"></a>
+<h2>50.2 Tuning-Tipps </h2>
+<hr>
+<ul>
+<li><a href="k100314.html#sectlevel2id050002">50.2 Tuning-Tipps</a>
+<ul>
+<li><a href="k100314.html#tuningstring">50.2.1 String und StringBuilder</a>
+<ul>
+<li><a href="k100314.html#sectlevel4id050002001001">String-Verkettung</a>
+<li><a href="k100314.html#sectlevel4id050002001002">Einf&uuml;gen und L&ouml;schen in Strings</a>
+<li><a href="k100314.html#sectlevel4id050002001003">Die Methode toString der Klasse StringBuilder</a>
+<li><a href="k100314.html#sectlevel4id050002001004">Die Unver&auml;nderlichkeit von String-Objekten</a>
+<li><a href="k100314.html#sectlevel4id050002001005">Durchlaufen von Zeichenketten</a>
+<li><a href="k100314.html#sectlevel4id050002001006">Das Interface CharSequence und die Methode
+toString</a>
+</ul>
+<li><a href="k100314.html#sectlevel3id050002002">50.2.2 Methodenaufrufe</a>
+<li><a href="k100314.html#tuningvectorlist">50.2.3 Vektoren und Listen</a>
+<li><a href="k100314.html#sectlevel3id050002004">50.2.4 Dateizugriffe</a>
+<ul>
+<li><a href="k100314.html#sectlevel4id050002004001">Schreiben von Streams</a>
+<li><a href="k100314.html#sectlevel4id050002004002">Lesen von Streams</a>
+<li><a href="k100314.html#sectlevel4id050002004003">RandomAccess-Dateien</a>
+</ul>
+<li><a href="k100314.html#sectlevel3id050002005">50.2.5 Speicher-Optimierung</a>
+</ul>
+</ul>
+<hr>
+
+
+<!-- Section -->
+<a name="tuningstring"></a>
+<h3>50.2.1 String und StringBuilder </h3>
+
+
+<!-- Section -->
+<a name="sectlevel4id050002001001"></a>
+<h4><a name="ixa103641">String-Verkettung</a></h4>
+
+<p>
+In Java gibt es zwei unterschiedliche Klassen <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+und <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+zur Verarbeitung von Zeichenketten, deren prinzipielle Eigenschaften
+in <a href="k100070.html#kapitelstrings">Kapitel 11</a> erl&auml;utert
+wurden. Java-Anf&auml;nger verwenden meist haupts&auml;chlich die
+Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>,
+denn sie stellt die meisten Methoden zur Zeichenkettenextraktion und
+-verarbeitung zur Verf&uuml;gung und bietet mit dem +-Operator eine
+bequeme M&ouml;glichkeit, Zeichenketten miteinander zu verketten.
+
+<p>
+Da&szlig; diese Bequemlichkeit ihren Preis hat, zeigt folgender Programmausschnitt:
+<a name="slowstringconcat"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font>String s;
+<font color="#555555">002 </font>s = <font color="#0000FF">""</font>;
+<font color="#555555">003 </font><font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; 20000; ++i) {
+<font color="#555555">004 </font> s += <font color="#0000FF">"x"</font>;
+<font color="#555555">005 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.1: Langsame String-Verkettung</i></p>
+
+<p>
+Das Programmfragment hat die Aufgabe, einen String zu erstellen, der
+aus 20000 aneinandergereihten &#187;x&#171; besteht. Das ist zwar
+nicht sehr praxisnah, illustriert aber die h&auml;ufig vorkommende
+Verwendung des +=-Operators auf Strings. Der obige Code ist sehr ineffizient,
+denn er l&auml;uft langsam und belastet das Laufzeitsystem durch 60000
+tempor&auml;re Objekte, die alloziert und vom Garbage Collector wieder
+freigegeben werden m&uuml;ssen. Der Compiler &uuml;bersetzt das Programmfragment
+etwa so:
+<a name="listingid050002"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font>String s;
+<font color="#555555">002 </font>s = <font color="#0000FF">""</font>;
+<font color="#555555">003 </font><font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; 20000; ++i) {
+<font color="#555555">004 </font> s = <font color="#0000AA">new</font> StringBuilder(s).append(<font color="#0000FF">"x"</font>).toString();
+<font color="#555555">005 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.2: Wie der Java-Compiler String-Verkettungen &uuml;bersetzt</i></p>
+
+<p>
+Dieser Code ist in mehrfacher Hinsicht ungl&uuml;cklich. Pro Schleifendurchlauf
+wird ein tempor&auml;res <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekt
+alloziert und mit dem zuvor erzeugten String initialisiert. Der Konstruktor
+von <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+erzeugt ein internes Array (also eine weitere Objektinstanz), um die
+Zeichenkette zu speichern. Immerhin ist dieses Array 16 Byte gr&ouml;&szlig;er
+als eigentlich erforderlich, so dass der nachfolgende Aufruf von <a href="index_a.html#ixb100546"><font color=#000080><tt>append</tt></font></a>
+das Array nicht neu allozieren und die Zeichen umkopieren muss. Schlie&szlig;lich
+wird durch den Aufruf von <a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a>
+ein neues <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekt
+erzeugt und <font color="#000077"><tt>s</tt></font> zugewiesen. Auf
+diese Weise werden pro Schleifendurchlauf drei tempor&auml;re Objekte
+erzeugt, und der Code ist durch das wiederholte Kopieren der Zeichen
+im Konstruktor von <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+sehr ineffizient.
+
+<p>
+Eine eminente Verbesserung ergibt sich, wenn die Klasse <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+und ihre Methode <a name="ixa103642"><a href="index_a.html#ixb100546"><font color=#000080><tt>append</tt></font></a></a>
+direkt verwendet werden:
+<a name="listingid050003"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font>String s;
+<font color="#555555">002 </font>StringBuilder sb = <font color="#0000AA">new</font> StringBuilder(1000);
+<font color="#555555">003 </font><font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; 20000; ++i) {
+<font color="#555555">004 </font> sb.append(<font color="#0000FF">"x"</font>);
+<font color="#555555">005 </font>}
+<font color="#555555">006 </font>s = sb.toString();</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.3: Performante String-Verkettungen mit StringBuilder.append</i></p>
+
+<p>
+Hier wird zun&auml;chst ein <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+erzeugt und mit einem 1000 Zeichen gro&szlig;en Puffer versehen. Da
+die <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Klasse
+sich die L&auml;nge der gespeicherten Zeichenkette merkt, kann der
+Aufruf <font color="#000077"><tt>append("x")</tt></font> meist in
+konstanter Laufzeit erfolgen. Dabei ist ein Umkopieren nur dann erforderlich,
+wenn der interne Puffer nicht mehr gen&uuml;gend Platz bietet, um
+die an <a href="index_a.html#ixb100546"><font color=#000080><tt>append</tt></font></a>
+&uuml;bergebenen Daten zu &uuml;bernehmen. In diesem Fall wird ein
+gr&ouml;&szlig;eres Array alloziert und der Inhalt des bisherigen
+Puffers umkopiert. In der Summe ist die letzte Version etwa um den
+Faktor 10 schneller als die ersten beiden und erzeugt 60000 tempor&auml;re
+Objekte weniger.
+
+<p>
+Interessant ist dabei der Umfang der Puffervergr&ouml;&szlig;erung,
+den das <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekt
+vornimmt, denn er bestimmt, wann bei fortgesetztem Aufruf von <a href="index_a.html#ixb100546"><font color=#000080><tt>append</tt></font></a>
+das n&auml;chste Mal umkopiert werden muss. Anders als beispielsweise
+bei der Klasse <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>,
+die einen ver&auml;nderbaren <a name="ixa103643"><i>Ladefaktor</i></a>
+besitzt, <i>verdoppelt</i> sich die Gr&ouml;&szlig;e eines <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekts
+bei jeder Kapazit&auml;tserweiterung. Dadurch wird zwar m&ouml;glicherweise
+mehr Speicher als n&ouml;tig alloziert, aber die Anzahl der Kopiervorg&auml;nge
+w&auml;chst h&ouml;chstens logarithmisch mit der Gesamtmenge der eingef&uuml;gten
+Daten. In unserem Beispiel kann der interne Puffer zun&auml;chst 1000
+Zeichen aufnehmen, wird beim n&auml;chsten &Uuml;berlauf auf etwa
+2000 Zeichen vergr&ouml;&szlig;ert, dann auf 4000, 8000, 16000 und
+schlie&szlig;lich auf 32000 Zeichen. H&auml;tten wir die initiale
+Gr&ouml;&szlig;e auf 20000 Zeichen gesetzt, w&auml;re sogar &uuml;berhaupt
+kein Kopiervorgang erforderlich geworden und das Programm h&auml;tte
+12000 Zeichen weniger alloziert.
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100%>
+<tr>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=1></td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top width=1000>
+
+<p>
+Bei der Verwendung der Operatoren + und += auf <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekten
+sollte man zus&auml;tzlich bedenken, dass deren Laufzeit nicht konstant
+ist (bzw. ausschlie&szlig;lich von der L&auml;nge des anzuh&auml;ngenden
+Strings abh&auml;ngt). Tats&auml;chlich h&auml;ngt sie auch stark
+von der L&auml;nge des Strings ab, an den angeh&auml;ngt werden soll,
+denn die Laufzeit eines Kopiervorgangs w&auml;chst nun einmal proportional
+zur L&auml;nge des zu kopierenden Objekts. Damit w&auml;chst das Laufzeitverhalten
+der Schleife in <a href="k100314.html#slowstringconcat">Listing 50.1</a>
+nicht linear, sondern ann&auml;hernd quadratisch. Es verschlechtert
+sich also mit zunehmender L&auml;nge der Schleife &uuml;berproportional.</td>
+<td><img src="trp1_1.gif" width=2></td>
+<td valign=top>
+<table border=0 cellspacing=0 cellpadding=1 width=100% bgcolor="#CC0000">
+<tr>
+<td><font color="#FFFFFF">&nbsp;Warnung&nbsp;</font></td>
+</tr>
+</table>
+</td>
+<td width=1 align=left valign=top bgcolor="#CC0000"><img src="trp1_1.gif"></td>
+</tr>
+</table>
+
+
+<!-- Section -->
+<a name="sectlevel4id050002001002"></a>
+<h4>Einf&uuml;gen und L&ouml;schen in Strings </h4>
+
+<p>
+Ein immer noch deutlicher, wenn auch nicht ganz so drastischer Vorteil
+bei der Verwendung von <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+ergibt sich beim Einf&uuml;gen von Zeichen <i>am vorderen Ende</i>
+des Strings:
+<a name="listingid050004"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font>String s;
+<font color="#555555">002 </font>s = <font color="#0000FF">""</font>;
+<font color="#555555">003 </font><font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; 10000; ++i) {
+<font color="#555555">004 </font> s = <font color="#0000FF">"x"</font> + s;
+<font color="#555555">005 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.4: Langsames Einf&uuml;gen in einen String</i></p>
+
+<p>
+In diesem Beispiel wird wiederholt ein Zeichen vorne in den String
+eingef&uuml;gt. Der Compiler wandelt das Programm auch hier in wiederholte
+Aufrufe von <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Methoden
+um, wobei unn&ouml;tig viele Zwischenobjekte entstehen und unn&ouml;tig
+oft kopiert werden muss. Eine bessere L&ouml;sung kann man auch hier
+durch direkte Verwendung eines <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekts
+erzielen:
+<a name="listingid050005"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font>String s;
+<font color="#555555">002 </font>StringBuilder sb = <font color="#0000AA">new</font> StringBuilder(1000);
+<font color="#555555">003 </font><font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; 10000; ++i) {
+<font color="#555555">004 </font> sb.insert(0, <font color="#0000FF">"x"</font>);
+<font color="#555555">005 </font>}
+<font color="#555555">006 </font>s = sb.toString();</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.5: Schnelles Einf&uuml;gen in einen String</i></p>
+
+<p>
+Im Test war die Laufzeit dieser Variante etwa um den Faktor vier besser
+als die der ersten Version. Au&szlig;erdem wird nicht ein einziges
+tempor&auml;res Objekt erzeugt, so dass zus&auml;tzlich das Memory-Subsystem
+und der Garbage Collector entlastet werden.
+<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>
+Seit dem JDK 1.2 gibt es in der Klasse <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+(beziehungsweise in der Klasse <a href="index_s.html#ixb100119"><font color=#000080><tt>StringBuffer</tt></font></a>)
+eine Methode <a name="ixa103644"><a href="index_d.html#ixb100549"><font color=#000080><tt>delete</tt></font></a></a>,
+mit der ein Teil der Zeichenkette gel&ouml;scht werden kann. Dadurch
+k&ouml;nnen beispielsweise Programmteile der folgenden Art beschleunigt
+werden:
+<font color="#000077">
+<pre>
+String sub1 = s.substring(0, 1000) + s.substring(2000);
+</pre>
+</font>
+
+<p>
+Anstatt hier die ersten 1000 Zeichen mit allen Zeichen ab Position
+2000 zu verbinden, kann unter Verwendung eines <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilders</tt></font></a>
+auch direkt das gew&uuml;nschte St&uuml;ck gel&ouml;scht werden:
+<font color="#000077">
+<pre>
+String sub2 = sb.delete(1000, 2000).toString();
+</pre>
+</font>
+</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>
+
+
+<!-- Section -->
+<a name="sectlevel4id050002001003"></a>
+<h4>Die Methode toString der Klasse StringBuilder </h4>
+
+<p>
+Den vorangegangenen Abschnitten kann man entnehmen, dass die Verwendung
+der Klasse <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+meist dann sinnvoll ist, wenn die Zeichenkette zun&auml;chst aus vielen
+kleinen Teilen <i>aufgebaut</i> werden soll oder wenn sie sich h&auml;ufig
+&auml;ndert. Ist der String dagegen fertig konstruiert oder muss auf
+einen vorhandenen String lesend zugegriffen werden, geht dies im allgemeinen
+mit den vielseitigeren Methoden der Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+besser. Um einen <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+in einen <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+zu konvertieren, wird die Methode <a name="ixa103645"><a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a></a>
+aufgerufen, die durch einen kleinen Trick sehr effizient arbeitet.
+Anstatt beim Aufruf von <a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a>
+einen Kopiervorgang zu starten, teilen sich <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-
+und <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekt
+nach dem Aufruf das interne Zeichenarray, d.h. beide Objekte verwenden
+ein- und denselben Puffer. Normalerweise w&auml;re diese Vorgehensweise
+indiskutabel, denn nach der n&auml;chsten &Auml;nderung des <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekts
+h&auml;tte sich dann auch der Inhalt des <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekts
+ver&auml;ndert (was per Definition nicht erlaubt ist).
+
+<p>
+Um das zu verhindern, wird vom Konstruktor der <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Klasse
+w&auml;hrend des Aufrufs von <a href="index_t.html#ixb100327"><font color=#000080><tt>toString</tt></font></a>
+ein <i>shared</i>-Flag im <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekt
+gesetzt. Dieses wird bei allen <i>ver&auml;ndernden</i> <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Methoden
+abgefragt und f&uuml;hrt dazu, dass - wenn es gesetzt ist - der Pufferinhalt
+vor der Ver&auml;nderung kopiert und die &Auml;nderung auf der Kopie
+vorgenommen wird. Ein echter Kopiervorgang wird also solange nicht
+erforderlich, wie auf den <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+nicht schreibend zugegriffen wird.
+
+<!-- Section -->
+
+<a name="sectlevel4id050002001004"></a>
+<h4>Die Unver&auml;nderlichkeit von String-Objekten </h4>
+
+<p>
+Da die Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+keine M&ouml;glichkeit bietet, die gespeicherte Zeichenkette nach
+der Instanzierung des Objekts zu ver&auml;ndern, k&ouml;nnen einige
+Operationen auf Zeichenketten sehr effizient implementiert werden.
+So erfordert beispielsweise die einfache Zuweisung zweier <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekte
+lediglich das Kopieren eines Zeigers, ohne dass durch <a name="ixa103646"><i>Aliasing</i></a>
+die Gefahr besteht, beim &Auml;ndern eines Strings versehentlich weitere
+Objekte zu &auml;ndern, die auf denselben Speicherbereich zeigen.
+
+<p>
+Soll ein <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+physikalisch kopiert werden, kann das mit Hilfe eines speziellen Konstruktors
+erreicht werden:
+<font color="#000077">
+<pre>
+String s2 = new String(s1);
+</pre>
+</font>
+
+<p>
+Da der interne Puffer hierbei kopiert wird, ist der Aufruf nat&uuml;rlich
+ineffizienter als die einfache Zuweisung.
+
+<p>
+Auch die Methode <a name="ixa103647"><a href="index_s.html#ixb100524"><font color=#000080><tt>substring</tt></font></a></a>
+der Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+konnte sehr effizient implementiert werden. Sie erzeugt zwar ein neues
+<a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekt,
+aber den internen Zeichenpuffer teilt es sich mit dem bisherigen Objekt.
+Lediglich die Membervariablen, in denen die Startposition und relevante
+L&auml;nge des Puffers festgehalten werden, m&uuml;ssen im neuen Objekt
+angepasst werden. Dadurch ist auch das Extrahieren von langen Teilzeichenketten
+recht performant. Dasselbe gilt f&uuml;r die Methode <a name="ixa103648"><a href="index_t.html#ixb100525"><font color=#000080><tt>trim</tt></font></a></a>,
+die ebenfalls <a href="index_s.html#ixb100524"><font color=#000080><tt>substring</tt></font></a>
+verwendet und daher keine Zeichen kopieren muss.
+
+<!-- Section -->
+
+<a name="sectlevel4id050002001005"></a>
+<h4>Durchlaufen von Zeichenketten </h4>
+
+<p>
+Soll ein <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+durchlaufen werden, so kann mit der Methode <a href="index_l.html#ixb100275"><font color=#000080><tt>length</tt></font></a>
+seine L&auml;nge ermittelt werden, und durch wiederholten Aufruf von
+<a href="index_c.html#ixb100522"><font color=#000080><tt>charAt</tt></font></a>
+k&ouml;nnen alle Zeichen nacheinander abgeholt werden. Alternativ
+k&ouml;nnte man auch zun&auml;chst ein Zeichenarray allozieren und
+durch Aufruf von <a name="ixa103649"><a href="index_g.html#ixb102742"><font color=#000080><tt>getChars</tt></font></a></a>
+alle Zeichen hineinkopieren. Beim sp&auml;teren Durchlaufen w&auml;re
+dann kein Methodenaufruf mehr erforderlich, sondern die einzelnen
+Array-Elemente k&ouml;nnten direkt verwendet werden. Die Laufzeitunterschiede
+zwischen beiden Varianten sind allerdings minimal und werden in der
+Praxis kaum ins Gewicht fallen (da die Klasse <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>
+als <a href="index_f.html#ixb100401"><font color=#000080><tt>final</tt></font></a>
+deklariert wurde und die Methode <a href="index_c.html#ixb100522"><font color=#000080><tt>charAt</tt></font></a>
+nicht <a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a>
+ist, kann sie sehr performant aufgerufen werden).
+
+<!-- Section -->
+
+<a name="sectlevel4id050002001006"></a>
+<h4>Das Interface <a name="ixa103650">CharSequence</a> und die Methode
+toString </h4>
+
+<p>
+Wenn Sie eine Zeichenkette aus Einzelst&uuml;cken zusammensetzen verwenden
+Sie am Besten die Klasse <font color="#000077"><tt>StringBuilder</tt></font>.
+Doch wenn Sie diese Zeichenkette anschlie&szlig;end als Parameter
+oder R&uuml;ckgabewert &uuml;bergeben, wird dieser h&auml;ufig &uuml;ber
+die Methode <font color="#000077"><tt>toString</tt></font> in einen
+&auml;quivalenten <font color="#000077"><tt>String</tt></font> umgewandelt.
+Wird die Zeichenkette anschlie&szlig;end weiter bearbeitet, wird der
+&uuml;bergebene <font color="#000077"><tt>String</tt></font> anschlie&szlig;end
+wieder in einen <font color="#000077"><tt>StringBuilder</tt></font>
+umgewandelt und so weiter.
+
+<p>
+Sie k&ouml;nnen sich diese unn&ouml;tigen Kopieroperationen allerdings
+auch sparen und Ihren Code gleichzeitig wesentlich lesbarer machen,
+indem Sie in diesen F&auml;llen einfach in der Methodensignatur einen
+Parameter vom Typ <font color="#000077"><tt>StringBuilder</tt></font>
+definieren und das Objekt direkt &uuml;bergeben.
+
+<p>
+K&ouml;nnen Sie die Signatur der Methode allerdings nicht &auml;ndern
+- etwa, weil die Methode auch mit gew&ouml;hnlichen Strings aufgerufen
+werden soll, h&auml;lt das JDK seit der Version 5 das Interface <a href="index_c.html#ixb100552"><font color=#000080><tt>CharSequence</tt></font></a>
+f&uuml;r Sie bereit, welches bereits in <a href="k100075.html#charsequence">Abschnitt 11.5</a>
+vorgestellt wurde. Dieses Interface wird sowohl von der Klasse <font color="#000077"><tt>String</tt></font>
+als auch von <font color="#000077"><tt>StringBuilder</tt></font> implementiert
+und gestattet es Objekte beiden Typs zu &uuml;bergeben.
+
+<!-- Section -->
+
+<a name="sectlevel3id050002002"></a>
+<h3>50.2.2 Methodenaufrufe </h3>
+
+<p>
+Eine der h&auml;ufigsten Operationen in objektorientierten Programmiersprachen
+ist der Aufruf einer Methode an einer Klasse oder einem Objekt. Generell
+werden Methodenaufrufe in Java recht performant ausgef&uuml;hrt. Ihr
+Laufzeitverhalten ist jedoch stark von ihrer Signatur und ihren Attributen
+abh&auml;ngig. <a href="k100314.html#methperformance">Tabelle 50.1</a>
+gibt einen &Uuml;berblick &uuml;ber die Laufzeit (in msec.) von 10
+Millionen Aufrufen einer trivialen Methode unter unterschiedlichen
+Bedingungen. Alle Messungen wurden mit dem JDK 1.2 Beta 4 auf einem
+PentiumII-266 unter Windows 95 vorgenommen. <a name="methperformance"></a>
+
+<p>
+<table cols=3 border width=66%>
+
+<tr>
+<td valign=top align=left width=66%><b>Signatur/Attribute </b></td>
+<td valign=top align=left width=16%><b>Ohne JIT </b></td>
+<td valign=top align=left width=16%><b>Mit JIT</b></td></tr>
+<tr>
+<td valign=top align=left>public </td>
+<td valign=top align=left>5650 </td>
+<td valign=top align=left>280</td></tr>
+<tr>
+<td valign=top align=left>public, mit 4 Parametern </td>
+<td valign=top align=left>7800 </td>
+<td valign=top align=left>390</td></tr>
+<tr>
+<td valign=top align=left>public static </td>
+<td valign=top align=left>5060 </td>
+<td valign=top align=left>110</td></tr>
+<tr>
+<td valign=top align=left>protected </td>
+<td valign=top align=left>5770 </td>
+<td valign=top align=left>280</td></tr>
+<tr>
+<td valign=top align=left>private </td>
+<td valign=top align=left>5820 </td>
+<td valign=top align=left>50</td></tr>
+<tr>
+<td valign=top align=left>public synchronized </td>
+<td valign=top align=left>9500 </td>
+<td valign=top align=left>4660</td></tr>
+<tr>
+<td valign=top align=left>public final </td>
+<td valign=top align=left>6260 </td>
+<td valign=top align=left>50</td></tr>
+</table>
+<p><i>
+Tabelle 50.1: Geschwindigkeit von Methodenaufrufen</i></p>
+
+<p>
+Dabei fallen einige Dinge auf:
+<ul>
+<li>In jedem Fall bringt der JIT einen erheblichen Geschwindigkeitsvorteil.
+Er liegt (mit Ausnahme der <a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a>-Methode)
+in diesem Beispiel durchweg bei &uuml;ber einer Zehnerpotenz.
+<li>Methoden des Typs <a href="index_f.html#ixb100401"><font color=#000080><tt>final</tt></font></a>
+und <a href="index_p.html#ixb100085"><font color=#000080><tt>private</tt></font></a>
+werden am schnellsten ausgef&uuml;hrt, insbesondere bei aktiviertem
+JIT.
+<li>Klassenmethoden werden schneller ausgef&uuml;hrt als Instanzmethoden.
+<li>Die &Uuml;bergabe von Parametern erfordert zus&auml;tzliche Zeit.
+In unserem Beispiel wurden vier Argumente (<a href="index_i.html#ixb100244"><font color=#000080><tt>int</tt></font></a>,
+<a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>,
+<a href="index_d.html#ixb100247"><font color=#000080><tt>double</tt></font></a>
+und <a href="index_b.html#ixb100072"><font color=#000080><tt>boolean</tt></font></a>)
+&uuml;bergeben.
+<li>Mit Abstand am langsamsten ist der Aufruf von Methoden, die das
+<a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a>-Attribut
+verwenden, denn der Zugriff auf die Sperre zur Synchronisation in
+Multi-Threading-Umgebungen kostet erhebliche Zeit. Auch der Just-In-Time-Compiler
+bringt hier keine nennenswerten Vorteile.
+</ul>
+
+<p>
+Weiterhin ist zu beachten, dass der polymorphe Aufruf von Methoden
+Zeit kostet (was nicht aus dieser Tabelle abgelesen werden kann).
+Ist beispielsweise aus einer Klasse <i>A</i> eine weitere Klasse <i>B</i>
+abgeleitet, so ist der Aufruf von Methoden auf einem Objekt des Typs
+<i>A</i> kostspieliger als der auf einem Objekt des Typs <font color="#000077"><tt>B</tt></font>.
+
+<p>
+Aus diesen Ergebnissen allgemeing&uuml;ltige Empfehlungen abzuleiten,
+ist schwierig. Zwar empfiehlt es sich offensichtlich, Methoden als
+<a name="ixa103651"><a href="index_p.html#ixb100085"><font color=#000080><tt>private</tt></font></a></a>
+bzw. <a name="ixa103652"><a href="index_f.html#ixb100401"><font color=#000080><tt>final</tt></font></a></a>
+zu deklarieren, wenn sicher ist, dass sie in abgeleiteten Klassen
+nicht aufgerufen bzw. &uuml;berlagert werden sollen. Auch k&ouml;nnte
+man versuchen, verst&auml;rkt Klassenmethoden zu verwenden oder zur
+Vermeidung von polymorphen Aufrufen die Vererbungshierachie zu beschr&auml;nken
+oder mit Hilfe des Attributs <a href="index_f.html#ixb100401"><font color=#000080><tt>final</tt></font></a>
+ganz abzuschneiden. All diese Entscheidungen h&auml;tten aber einen
+starken Einfluss auf das Klassendesign der Anwendung und k&ouml;nnten
+sich leicht an anderer Stelle als Sackgasse herausstellen.
+
+<p>
+Der einzig wirklich allgemeing&uuml;ltige Rat besteht darin, Methoden
+nur dann als <a name="ixa103653"><a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a></a>
+zu deklarieren, wenn es wirklich erforderlich ist. Eine Methode, die
+keine Membervariablen verwendet, die gleichzeitig von anderen Threads
+manipuliert werden, braucht auch nicht synchronisiert zu werden. Eine
+Anwendung, die nur einen einzigen Thread besitzt und deren Methoden
+nicht von Hintergrundthreads aufgerufen werden, braucht &uuml;berhaupt
+keine synchronisierten Methoden in eigenen Klassen.
+
+<!-- Section -->
+
+<a name="tuningvectorlist"></a>
+<h3>50.2.3 Vektoren und Listen </h3>
+
+<p>
+Ein <a name="ixa103654"><a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a></a>
+ist ein bequemes Hilfsmittel, um Listen von Objekten zu speichern,
+auf die sowohl sequenziell als auch wahlfrei zugriffen werden kann.
+Aufgrund seiner einfachen Anwendung und seiner Flexibilit&auml;t bez&uuml;glich
+der Art und Menge der zu speichernden Elemente wird er in vielen Programmen
+ausgiebig verwendet. Bei falschem Einsatz k&ouml;nnen Vektoren durchaus
+zum Performance-Killer werden, und wir wollen daher einige Hinweise
+zu ihrer Verwendung geben.
+
+<p>
+Zun&auml;chst einmal ist der Datenpuffer eines Vektors als Array implementiert.
+Da die Gr&ouml;&szlig;e von Arrays nach ihrer Initialisierung nicht
+mehr ver&auml;ndert werden kann, erfordert das Einf&uuml;gen neuer
+Elemente m&ouml;glicherweise das Allozieren eines neuen Puffers und
+das Umkopieren der vorhandenen Elemente. Ein <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+besitzt dazu die beiden Attribute <i>Kapazit&auml;t</i> und <i>Ladefaktor</i>.
+Die Kapazit&auml;t gibt an, wie viele Elemente insgesamt aufgenommen
+werden k&ouml;nnen, also wie gro&szlig; der interne Puffer ist. Der
+Ladefaktor bestimmt, um wie viele Elemente der interne Puffer erweitert
+wird, wenn beim Einf&uuml;gen eines neuen Elements nicht mehr ausreichend
+Platz vorhanden ist. Je kleiner die anf&auml;ngliche Kapazit&auml;t
+und der Ladefaktor sind, desto h&auml;ufiger ist beim fortgesetzten
+Einf&uuml;gen von Elementen ein zeitaufw&auml;ndiges Umkopieren erforderlich.
+
+<p>
+Wird ein <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+ohne Argumente instanziert, so hat sein Puffer eine anf&auml;ngliche
+Kapazit&auml;t von 10 Objekten und der Ladefaktor ist 0. Letzteres
+bedeutet, dass die Kapazit&auml;t bei jeder Erweiterung <i>verdoppelt</i>
+wird (analog zur Klasse <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>,
+s. <a href="k100314.html#tuningstring">Abschnitt 50.2.1</a>). Alternativ
+kann die Kapazit&auml;t oder auch beide Werte beim Instanzieren an
+den Konstruktor &uuml;bergeben werden. Durch die folgende Deklaration
+wird ein <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+mit einer anf&auml;nglichen Kapazit&auml;t von 100 Elementen und einem
+Ladefaktor von 50 angelegt:
+<font color="#000077">
+<pre>
+Vector v = new Vector(100, 50);
+</pre>
+</font>
+
+<p>
+Ein weiteres Problem der Klasse <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+ist, dass die meisten ihrer Methoden als <a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a>
+deklariert wurden. Dadurch kann ein <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+zwar sehr einfach als gemeinsame Datenstruktur mehrerer Threads verwendet
+werden. Die Zugriffsmethoden sind aber leider auch ohne Multi-Threading-Betrieb
+entsprechend langsam.
+<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>
+Seit der Version 1.2 des JDK stehen mit den Klassen <a name="ixa103655"><a href="index_l.html#ixb100695"><font color=#000080><tt>LinkedList</tt></font></a></a>
+und <a name="ixa103656"><a href="index_a.html#ixb100719"><font color=#000080><tt>ArrayList</tt></font></a></a>
+auch alternative Listenimplementierungen zur Verf&uuml;gung, die anstelle
+von <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+verwendet werden k&ouml;nnen. Hier ist jedoch Vorsicht geboten, soll
+das Programm nicht langsamer laufen als vorher. Die Klasse <a href="index_l.html#ixb100695"><font color=#000080><tt>LinkedList</tt></font></a>
+implementiert die Datenstruktur in klassischer Form als doppelt verkettete
+Liste ihrer Elemente. Zwar entfallen dadurch die Kopiervorg&auml;nge,
+die beim Erweitern des Arrays erforderlich waren. Durch die Vielzahl
+der allozierten Objekte, in denen die Listenelemente und die Zeiger
+gespeichert werden m&uuml;ssen, und die teilweise ineffiziente Implementierung
+einiger Grundoperationen (insbesondere <a href="index_a.html#ixb100727"><font color=#000080><tt>add</tt></font></a>)
+hat sich <a href="index_l.html#ixb100695"><font color=#000080><tt>LinkedList</tt></font></a>
+jedoch im Test als relativ ineffizient herausgestellt. Wesentlich
+bessere Ergebnisse gab es mit der Klasse <a href="index_a.html#ixb100719"><font color=#000080><tt>ArrayList</tt></font></a>.
+Sie ist &auml;hnlich wie <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+implementiert, verzichtet aber (wie die meisten 1.2er Collections)
+auf die <a href="index_s.html#ixb100715"><font color=#000080><tt>synchronized</tt></font></a>-Attribute
+und ist daher - insbesondere bei aktiviertem JIT und Zugriff mit <a href="index_a.html#ixb100727"><font color=#000080><tt>add</tt></font></a>
+und <a href="index_g.html#ixb100699"><font color=#000080><tt>get</tt></font></a>
+sehr - performant. </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>
+<a href="k100314.html#listenundvektoren">Listing 50.6</a> zeigt drei
+Methoden, die jeweils ein String-Array &uuml;bergeben bekommen und
+daraus eine bestimmte Anzahl von Elementen zur&uuml;ckgeben. Die erste
+Version verwendet einen <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>,
+die zweite eine <a href="index_l.html#ixb100695"><font color=#000080><tt>LinkedList</tt></font></a>
+und die dritte eine <a href="index_a.html#ixb100719"><font color=#000080><tt>ArrayList</tt></font></a>
+zur Datenspeicherung. Im Test war die dritte Version eindeutig die
+schnellste. Bei aktiviertem JIT und &Uuml;bergabe von 100000 Elementen,
+von denen jeweils die H&auml;lfte zur&uuml;ckgegeben wurden, war das
+Verh&auml;ltnis der Laufzeiten der drei Methoden etwa 3:18:1.
+<a name="listenundvektoren"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> String[] vtest1(String el[], <font color="#006699">int</font> retsize)
+<font color="#555555">002 </font>{
+<font color="#555555">003 </font> <font color="#00AA00">//Verwendet Vector</font>
+<font color="#555555">004 </font> Vector v = <font color="#0000AA">new</font> Vector(el.length + 10);
+<font color="#555555">005 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; el.length; ++i) {
+<font color="#555555">006 </font> v.addElement(el[i]);
+<font color="#555555">007 </font> }
+<font color="#555555">008 </font> String[] ret = <font color="#0000AA">new</font> String[retsize];
+<font color="#555555">009 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; retsize; ++i) {
+<font color="#555555">010 </font> ret[i] = (String)v.elementAt(i);
+<font color="#555555">011 </font> }
+<font color="#555555">012 </font> <font color="#0000AA">return</font> ret;
+<font color="#555555">013 </font>}
+<font color="#555555">014 </font>
+<font color="#555555">015 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> String[] vtest2(String el[], <font color="#006699">int</font> retsize)
+<font color="#555555">016 </font>{
+<font color="#555555">017 </font> <font color="#00AA00">//Verwendet LinkedList</font>
+<font color="#555555">018 </font> LinkedList l = <font color="#0000AA">new</font> LinkedList();
+<font color="#555555">019 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; el.length; ++i) {
+<font color="#555555">020 </font> l.add(el[i]);
+<font color="#555555">021 </font> }
+<font color="#555555">022 </font> String[] ret = <font color="#0000AA">new</font> String[retsize];
+<font color="#555555">023 </font> Iterator it = l.iterator();
+<font color="#555555">024 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; retsize; ++i) {
+<font color="#555555">025 </font> ret[i] = (String)it.next();
+<font color="#555555">026 </font> }
+<font color="#555555">027 </font> <font color="#0000AA">return</font> ret;
+<font color="#555555">028 </font>}
+<font color="#555555">029 </font>
+<font color="#555555">030 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> String[] vtest3(String el[], <font color="#006699">int</font> retsize)
+<font color="#555555">031 </font>{
+<font color="#555555">032 </font> <font color="#00AA00">//Verwendet ArrayList</font>
+<font color="#555555">033 </font> ArrayList l = <font color="#0000AA">new</font> ArrayList(el.length + 10);
+<font color="#555555">034 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; el.length; ++i) {
+<font color="#555555">035 </font> l.add(el[i]);
+<font color="#555555">036 </font> }
+<font color="#555555">037 </font> String[] ret = <font color="#0000AA">new</font> String[retsize];
+<font color="#555555">038 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; retsize; ++i) {
+<font color="#555555">039 </font> ret[i] = (String)l.get(i);
+<font color="#555555">040 </font> }
+<font color="#555555">041 </font> <font color="#0000AA">return</font> ret;
+<font color="#555555">042 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.6: Vergleich von Listen und Vektoren</i></p>
+
+<p>
+Ist es dagegen erforderlich, viele Einf&uuml;gungen und L&ouml;schungen
+innerhalb der Liste vorzunehmen, sollte im allgemeinen eine zeigerbasierte
+Implementierung der arraybasierten vorgezogen werden. W&auml;hrend
+es bei letzterer stets erforderlich ist, einen Teil des Arrays umzukopieren,
+wenn ein Element eingef&uuml;gt oder gel&ouml;scht wird, brauchen
+bei den verzeigerten Datenstrukturen lediglich ein paar Verweise aktualisiert
+zu werden.
+
+<!-- Section -->
+
+<a name="sectlevel3id050002004"></a>
+<h3>50.2.4 Dateizugriffe </h3>
+
+
+<!-- Section -->
+<a name="sectlevel4id050002004001"></a>
+<h4>Schreiben von Streams </h4>
+
+<p>
+Seit dem JDK 1.1 gibt es die <a name="ixa103657"><a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a></a>-Klassen,
+mit denen <a name="ixa103658"><i>Character-Streams</i></a> verarbeitet
+werden k&ouml;nnen. Passend zur internen Darstellung des <a href="index_c.html#ixb100215"><font color=#000080><tt>char</tt></font></a>-Typs
+in Java verwenden sie 16-Bit breite UNICODE-Zeichen zur Ein- und Ausgabe.
+Um eine Datei zu erzeugen, kann ein <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>-Objekt
+angelegt werden, und die Zeichen werden mit den <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
+geschrieben. Um die Performance zu erh&ouml;hen, kann der <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>
+in einen <a name="ixa103659"><a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a></a>
+gekapselt werden, der mit Hilfe eines internen Zeichenpuffers die
+Anzahl der Schreibzugriffe reduziert. Im Test ergab sich dadurch ein
+Geschwindigkeitszuwachs um den Faktor drei bis vier gegen&uuml;ber
+dem ungepufferten Zugriff. Die von <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>
+verwendete Standard-Puffergr&ouml;&szlig;e von 8 kByte ist in aller
+Regel ausreichend, weitere Vergr&ouml;&szlig;erungen bringen keine
+nennenswerten Beschleunigungen.
+
+<p>
+Das Dilemma der <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Klassen
+besteht darin, dass die meisten externen Dateien mit 8-Bit-Zeichen
+arbeiten, statt mit 16-Bit-UNICODE-Zeichen. Ein <a href="index_f.html#ixb100961"><font color=#000080><tt>FileWriter</tt></font></a>
+f&uuml;hrt also vor der Ausgabe eine Konvertierung der UNICODE-Zeichen
+durch, um sie im korrekten Format abzuspeichern. Der Aufruf der dazu
+verwendeten Methoden der Klasse <a name="ixa103660"><a href="index_c.html#ixb100971"><font color=#000080><tt>CharToByteConverter</tt></font></a></a>
+aus dem Paket <a href="index_s.html#ixb100972"><font color=#000080><tt>sun.io</tt></font></a>
+kostet nat&uuml;rlich Zeit und vermindert die Performance der <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Klasse.
+Wesentlich schneller sind die (&auml;lteren) <a name="ixa103661"><a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a></a>-Klassen,
+die nicht mit Zeichen, sondern mit Bytes arbeiten. Sie f&uuml;hren
+keine aufw&auml;ndige Konvertierung durch, sondern geben je Zeichen
+einfach dessen niederwertige 8 Bit aus. Das spart viel Zeit und f&uuml;hrte
+im Test zu einer nochmals um den Faktor drei bis vier beschleunigten
+Ausgabe (wenn auch der <a name="ixa103662"><a href="index_f.html#ixb101005"><font color=#000080><tt>FileOutputStream</tt></font></a></a>
+in einen <a name="ixa103663"><a href="index_b.html#ixb101010"><font color=#000080><tt>BufferedOutputStream</tt></font></a></a>
+eingeschlossen wurde).
+
+<p>
+Die <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>-Klassen
+sind also immer dann den <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-Klassen
+vorzuziehen, wenn entweder sowieso Bin&auml;rdaten ausgegeben werden
+sollen oder wenn sichergestellt ist, dass keine UNICODE-Zeichen verwendet
+werden, die durch das simple Abschneiden der oberen 8 Bit falsch ausgegeben
+w&uuml;rden. Da der UNICODE-Zeichensatz in den ersten 256 Zeichen
+zum ISO-8859-1-Zeichensatz kompatibel ist, sollten sich f&uuml;r die
+meisten europ&auml;ischen und angels&auml;chsischen Sprachen keine
+Probleme ergeben, wenn zur Ausgabe von Zeichen die <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>-Klassen
+verwendet werden.
+
+<p>
+<a href="k100314.html#streamwriteperformance">Listing 50.7</a> zeigt
+das Erzeugen einer etwa 300 kByte gro&szlig;en Datei, bei der zun&auml;chst
+die <a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-
+und dann die <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>-Klassen
+verwendet wurden. Im Test lag die Ausf&uuml;hrungsgeschwindigkeit
+der zweiten Variante um etwa eine Zehnerpotenz &uuml;ber der ersten.
+<a name="streamwriteperformance"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> createfile1()
+<font color="#555555">002 </font><font color="#0000AA">throws</font> IOException
+<font color="#555555">003 </font>{
+<font color="#555555">004 </font> Writer writer = <font color="#0000AA">new</font> FileWriter(FILENAME);
+<font color="#555555">005 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; LINES; ++i) {
+<font color="#555555">006 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> j = 0; j &lt; 60; ++j) {
+<font color="#555555">007 </font> writer.write(<font color="#0000FF">'x'</font>);
+<font color="#555555">008 </font> }
+<font color="#555555">009 </font> writer.write(NL);
+<font color="#555555">010 </font> }
+<font color="#555555">011 </font> writer.close();
+<font color="#555555">012 </font>}
+<font color="#555555">013 </font>
+<font color="#555555">014 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> createfile4()
+<font color="#555555">015 </font><font color="#0000AA">throws</font> IOException
+<font color="#555555">016 </font>{
+<font color="#555555">017 </font> OutputStream os = <font color="#0000AA">new</font> BufferedOutputStream(
+<font color="#555555">018 </font> <font color="#0000AA">new</font> FileOutputStream(FILENAME)
+<font color="#555555">019 </font> );
+<font color="#555555">020 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> i = 0; i &lt; LINES; ++i) {
+<font color="#555555">021 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> j = 0; j &lt; 60; ++j) {
+<font color="#555555">022 </font> os.write(<font color="#0000FF">'x'</font>);
+<font color="#555555">023 </font> }
+<font color="#555555">024 </font> os.write(<font color="#0000FF">'\r'</font>);
+<font color="#555555">025 </font> os.write(<font color="#0000FF">'\n'</font>);
+<font color="#555555">026 </font> }
+<font color="#555555">027 </font> os.close();
+<font color="#555555">028 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.7: Performance von Writer und OutputStream</i></p>
+
+
+<!-- Section -->
+<a name="sectlevel4id050002004002"></a>
+<h4>Lesen von Streams </h4>
+
+<p>
+Die Performance des sequenziellen Lesens von Zeichen- oder Byte-Streams
+zeigt ein &auml;hnliches Verhalten wie die des sequenziellen Schreibens.
+Am langsamsten war der ungepufferte Zugriff mit der Klasse <a href="index_f.html#ixb100990"><font color=#000080><tt>FileReader</tt></font></a>.
+Die gr&ouml;&szlig;ten Geschwindigkeitsgewinne ergaben sich durch
+das Kapseln des <a href="index_f.html#ixb100990"><font color=#000080><tt>FileReader</tt></font></a>
+in einen <a href="index_b.html#ixb100993"><font color=#000080><tt>BufferedReader</tt></font></a>,
+die Performance lag um etwa eine Zehnerpotenz h&ouml;her als im ungepufferten
+Fall. Der Umstieg auf das byte-orientierte Einlesen mit den Klassen
+<a href="index_f.html#ixb101034"><font color=#000080><tt>FileInputStream</tt></font></a>
+und <a name="ixa103664"><a href="index_b.html#ixb101041"><font color=#000080><tt>BufferedInputStream</tt></font></a></a>
+brachte dagegen nur noch geringe Vorteile. M&ouml;glicherweise muss
+der zur Eingabekonvertierung in den <a href="index_r.html#ixb100983"><font color=#000080><tt>Reader</tt></font></a>-Klassen
+verwendete <a name="ixa103665"><a href="index_b.html#ixb100997"><font color=#000080><tt>ByteToCharConverter</tt></font></a></a>
+weniger Aufwand treiben, als ausgabeseitig n&ouml;tig war.
+
+<!-- Section -->
+
+<a name="sectlevel4id050002004003"></a>
+<h4>RandomAccess-Dateien </h4>
+
+<p>
+Der wahlfreie Zugriff auf eine Datei zum Lesen oder Schreiben erfolgt
+in Java mit der Klasse <a name="ixa103666"><a href="index_r.html#ixb101016"><font color=#000080><tt>RandomAccessFile</tt></font></a></a>.
+Da sie nicht Bestandteil der <a href="index_r.html#ixb100983"><font color=#000080><tt>Reader</tt></font></a>-
+<a href="index_w.html#ixb100956"><font color=#000080><tt>Writer</tt></font></a>-,
+<a href="index_i.html#ixb100642"><font color=#000080><tt>InputStream</tt></font></a>-
+oder <a href="index_o.html#ixb100673"><font color=#000080><tt>OutputStream</tt></font></a>-Hierarchien
+ist, besteht auch nicht die M&ouml;glichkeit, sie zum Zweck der Pufferung
+zu schachteln. Tats&auml;chlich ist der ungepufferte byteweise Zugriff
+auf ein <a href="index_r.html#ixb101016"><font color=#000080><tt>RandomAccessFile</tt></font></a>
+sehr langsam, er liegt etwa in der Gr&ouml;&szlig;enordnung des ungepufferten
+Zugriffs auf Character-Streams. Wesentlich schneller kann mit Hilfe
+der <a href="index_r.html#ixb100984"><font color=#000080><tt>read</tt></font></a>-
+und <a href="index_w.html#ixb100959"><font color=#000080><tt>write</tt></font></a>-Methoden
+gearbeitet werden, wenn nicht nur ein einzelnes, sondern ein ganzes
+Array von Bytes verarbeitet wird. Je nach Puffergr&ouml;&szlig;e und
+Verarbeitungsaufwand werden dann Geschwindigkeiten wie bei gepufferten
+Bytestreams oder h&ouml;her erzielt. Das folgende Beispiel zeigt,
+wie man mit einem 100 Byte gro&szlig;en Puffer eine Random-Access-Datei
+bereits sehr schnell lesen kann.
+<a name="listingid050008"></a>
+
+<p>
+<table border=0 cellspacing=0 cellpadding=0 width=100% bgcolor="#DDDDDD">
+<tr>
+<td valign=top>
+<font color="#000055">
+<pre>
+<font color="#555555">001 </font><font color="#0000AA">public</font> <font color="#0000AA">static</font> <font color="#006699">void</font> randomtest2()
+<font color="#555555">002 </font><font color="#0000AA">throws</font> IOException
+<font color="#555555">003 </font>{
+<font color="#555555">004 </font> RandomAccessFile file = <font color="#0000AA">new</font> RandomAccessFile(FILENAME, <font color="#0000FF">"rw"</font>);
+<font color="#555555">005 </font> <font color="#006699">int</font> cnt = 0;
+<font color="#555555">006 </font> <font color="#006699">byte</font>[] buf = <font color="#0000AA">new</font> <font color="#006699">byte</font>[100];
+<font color="#555555">007 </font> <font color="#0000AA">while</font> (<font color="#006699">true</font>) {
+<font color="#555555">008 </font> <font color="#006699">int</font> num = file.read(buf);
+<font color="#555555">009 </font> <font color="#0000AA">if</font> (num &lt;= 0) {
+<font color="#555555">010 </font> <font color="#0000AA">break</font>;
+<font color="#555555">011 </font> }
+<font color="#555555">012 </font> cnt += num;
+<font color="#555555">013 </font> }
+<font color="#555555">014 </font> System.out.println(cnt + <font color="#0000FF">" Bytes read"</font>);
+<font color="#555555">015 </font> file.close();
+<font color="#555555">016 </font>}</pre>
+</font>
+</td>
+</tr>
+</table>
+<i>
+Listing 50.8: Gepufferter Zugriff auf Random-Access-Dateien</i></p>
+
+<p>
+Das Programm liest die komplette Datei in St&uuml;cken von jeweils
+100 Byte ein. Der R&uuml;ckgabewert von <a href="index_r.html#ixb100984"><font color=#000080><tt>read</tt></font></a>
+gibt die tats&auml;chliche Zahl gelesener Bytes an. Sie entspricht
+normalerweise der Puffergr&ouml;&szlig;e, liegt aber beim letzten
+Datenpaket darunter, wenn die Dateigr&ouml;&szlig;e nicht zuf&auml;llig
+ein Vielfaches der Puffergr&ouml;&szlig;e ist. Die Performance von
+<font color="#000077"><tt>randomtest2</tt></font> ist sehr gut, sie
+lag auf dem Testrechner (Pentium II, 266 MHz, 128 MB, UW-SCSI) bei
+etwa 5 MByte pro Sekunde, was f&uuml;r ein Java-Programm sicherlich
+ein respektabler Wert ist. Ein wesentlicher Grund ist darin zu suchen,
+dass durch den programmeigenen Puffer ein Gro&szlig;teil der Methodenaufrufe
+zum Lesen einzelner Bytes vermieden werden (in diesem Fall sind es
+um den Faktor 100 weniger). Auf die gleiche Weise lassen sich auch
+die streamorientierten Dateizugriffe beschleunigen, wenn die Anwendung
+nicht unbedingt darauf angewiesen ist, <i>zeichenweise</i> zu lesen
+bzw. zu schreiben.
+
+<!-- Section -->
+
+<a name="sectlevel3id050002005"></a>
+<h3>50.2.5 Speicher-Optimierung </h3>
+
+<p>
+Neben den direkten Prozessoraktivit&auml;ten hat auch die Art und
+Weise, in der das Programm mit dem Hauptspeicher umgeht, einen erheblichen
+Einfluss auf dessen Performance. Einige der Aspekte, die dabei eine
+Rolle spielen, sind:
+<ul>
+<li>Jede Allozierung von Speicher kostet Rechenzeit. Der Speicher
+muss entweder vom Betriebssystem oder vom Laufzeitsystem der VM beschafft
+werden. Auch das (automatische) Initialisieren des Speichers kostet
+Zeit. Das Anlegen eines Arrays mit 1000 Elementen dauert wesentlich
+l&auml;nger als das eines mit 10 Elementen.
+<li>Objekte mit aufw&auml;ndigen Konstruktoren ben&ouml;tigen m&ouml;glicherweise
+viel Zeit zur Initialisierung. Bei ihnen kann es sinnvoll sein, sie
+zu &#187;recyceln&#171;. Dazu werden sie nach Gebrauch in einer geeigneten
+Datenstruktur gesammelt und k&ouml;nnen dem n&auml;chsten Interessenten
+(alternativ zur Erzeugung eines neuen Objekts) zur Verf&uuml;gung
+gestellt werden. Vor der Verwendung muss dieser das Objekt nat&uuml;rlich
+geeignet initialisieren.
+<li>Nicht mehr referenzierter Speicher belastet den Garbage Collector
+und erfordert CPU-Zeit, um dem Programm wieder zugef&uuml;hrt werden
+zu k&ouml;nnen.
+<li>In ung&uuml;nstigen F&auml;llen kann es sein, dass die VM den
+ben&ouml;tigten Speicher schrittweise in relativ kleinen St&uuml;cken
+beim Betriebssystem anfordert. Das kostet unter Umst&auml;nden sehr
+viel Zeit. In diesem Fall kann es sinnvoll sein, mit Hilfe des Schalters
+<a name="ixa103667"><a href="index_0.html#ixb102744"><font color=#000080><tt>-Xms</tt></font></a></a>
+den beim Start der VM anzufordernden Speicher auf einen h&ouml;heren
+Wert einzustellen.
+<li>Gro&szlig;e Mengen an tempor&auml;ren, kurzlebigen Objekten belasten
+die VM ebenfalls. Derartige Allokationsszenarien entstehen beispielsweise
+beim Modifizieren von Strings oder wenn primitive Typen mit Hilfe
+ihrer Wrapperklassen in Collections gespeichert werden sollen. In
+<a href="k100315.html#profilereinsatz">Abschnitt 50.3</a> zeigen wir
+ein harmlos aussehendes Programm, das beim Anlegen von 10 kByte Nutzdaten
+75 MByte Datenm&uuml;ll erzeugt.
+<li>Werden Referenzen auf Objekte nicht gel&ouml;scht, bleibt der
+zugeordnete Speicher belegt und der Garbage Collector kann ihn nicht
+wieder freigeben. Das belastet nicht nur die VM, die zunehmend neuen
+Speicher beim Betriebssystem anfordern muss, sondern f&uuml;hrt fr&uuml;her
+oder sp&auml;ter zum Absturz des Programms mit einem <a name="ixa103668"><a href="index_o.html#ixb102745"><font color=#000080><tt>OutOfMemoryError</tt></font></a></a>.
+<li>Derartige Speicherlecks entstehen, wenn eigentlich nicht mehr
+ben&ouml;tigte Objekte an &#187;lebenden&#171; Referenzen h&auml;ngen
+(also an Variablen, die im Programm noch ben&ouml;tigt werden). Lebende
+Referenzen sind die lokalen Variablen auf den Stacks aller laufenden
+Threads plus alle statischen Variablen des Programms. Zudem nat&uuml;rlich
+alle Variablen, die indirekt daran h&auml;ngen. Als Programmierer
+sollte man diesbez&uuml;glich den statischen Variablen (insbesondere
+wenn sie auf Collections verweisen) besonderes Augenmerk schenken.
+<li>Um dem Garbage Collector die Arbeit zu erleichtern, kann es sinnvoll
+sein, ihn in Programmpausen von Zeit zu Zeit durch Aufruf der Methode
+<a name="ixa103669"><a href="index_g.html#ixb100853"><font color=#000080><tt>gc</tt></font></a></a>
+der Klasse <a href="index_s.html#ixb100435"><font color=#000080><tt>System</tt></font></a>
+explizit aufzurufen. Das Programm kann ihm auch dadurch helfen, dass
+nicht mehr ben&ouml;tigten Objektvariablen explizit der Wert <a href="index_n.html#ixb100235"><font color=#000080><tt>null</tt></font></a>
+zugewiesen wird.
+</ul>
+<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="k100312.html">&nbsp;&lt;&lt;&nbsp;</a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100313.html">&nbsp;&nbsp;&lt;&nbsp;&nbsp;</a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100315.html">&nbsp;&nbsp;&gt;&nbsp;&nbsp;</a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100317.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>