diff options
| author | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
|---|---|---|
| committer | Sven Eisenhauer <sven@sven-eisenhauer.net> | 2023-11-10 15:11:48 +0100 |
| commit | 33613a85afc4b1481367fbe92a17ee59c240250b (patch) | |
| tree | 670b842326116b376b505ec2263878912fca97e2 /Master/Reference Architectures and Patterns/hjp5/html/k100314.html | |
| download | Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.gz Studium-33613a85afc4b1481367fbe92a17ee59c240250b.tar.bz2 | |
Diffstat (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100314.html')
| -rw-r--r-- | Master/Reference Architectures and Patterns/hjp5/html/k100314.html | 1055 |
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"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </a>
+<td align="right">Handbuch der Java-Programmierung, 5. Auflage
+<tr bgcolor="#EEFFCC">
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100312.html"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100313.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100315.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100317.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </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ügen und Lö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ä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äutert
+wurden. Java-Anfänger verwenden meist hauptsä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ügung und bietet mit dem +-Operator eine
+bequeme Möglichkeit, Zeichenketten miteinander zu verketten.
+
+<p>
+Daß 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 < 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 »x« besteht. Das ist zwar
+nicht sehr praxisnah, illustriert aber die häufig vorkommende
+Verwendung des +=-Operators auf Strings. Der obige Code ist sehr ineffizient,
+denn er läuft langsam und belastet das Laufzeitsystem durch 60000
+temporäre Objekte, die alloziert und vom Garbage Collector wieder
+freigegeben werden müssen. Der Compiler ü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 < 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 übersetzt</i></p>
+
+<p>
+Dieser Code ist in mehrfacher Hinsicht unglücklich. Pro Schleifendurchlauf
+wird ein temporä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öß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ß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ä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 < 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ächst ein <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>
+erzeugt und mit einem 1000 Zeichen großen Puffer versehen. Da
+die <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Klasse
+sich die Lä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ügend Platz bietet, um
+die an <a href="index_a.html#ixb100546"><font color=#000080><tt>append</tt></font></a>
+übergebenen Daten zu übernehmen. In diesem Fall wird ein
+größ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äre
+Objekte weniger.
+
+<p>
+Interessant ist dabei der Umfang der Puffervergröß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ä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änderbaren <a name="ixa103643"><i>Ladefaktor</i></a>
+besitzt, <i>verdoppelt</i> sich die Größe eines <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekts
+bei jeder Kapazitätserweiterung. Dadurch wird zwar möglicherweise
+mehr Speicher als nötig alloziert, aber die Anzahl der Kopiervorgänge
+wächst höchstens logarithmisch mit der Gesamtmenge der eingefügten
+Daten. In unserem Beispiel kann der interne Puffer zunächst 1000
+Zeichen aufnehmen, wird beim nächsten Überlauf auf etwa
+2000 Zeichen vergrößert, dann auf 4000, 8000, 16000 und
+schließlich auf 32000 Zeichen. Hätten wir die initiale
+Größe auf 20000 Zeichen gesetzt, wäre sogar überhaupt
+kein Kopiervorgang erforderlich geworden und das Programm hä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ätzlich bedenken, dass deren Laufzeit nicht konstant
+ist (bzw. ausschließlich von der Länge des anzuhängenden
+Strings abhängt). Tatsächlich hängt sie auch stark
+von der Länge des Strings ab, an den angehängt werden soll,
+denn die Laufzeit eines Kopiervorgangs wächst nun einmal proportional
+zur Länge des zu kopierenden Objekts. Damit wächst das Laufzeitverhalten
+der Schleife in <a href="k100314.html#slowstringconcat">Listing 50.1</a>
+nicht linear, sondern annähernd quadratisch. Es verschlechtert
+sich also mit zunehmender Länge der Schleife ü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"> Warnung </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ügen und Lö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ü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 < 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ügen in einen String</i></p>
+
+<p>
+In diesem Beispiel wird wiederholt ein Zeichen vorne in den String
+eingefü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ötig viele Zwischenobjekte entstehen und unnötig
+oft kopiert werden muss. Eine bessere Lö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 < 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ü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ßerdem wird nicht ein einziges
+temporäres Objekt erzeugt, so dass zusä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öscht werden kann. Dadurch
+kö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ünschte Stück gelö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"> JDK1.1-6.0 </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ächst aus vielen
+kleinen Teilen <i>aufgebaut</i> werden soll oder wenn sie sich häufig
+ä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äre diese Vorgehensweise
+indiskutabel, denn nach der nächsten Änderung des <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Objekts
+hätte sich dann auch der Inhalt des <a href="index_s.html#ixb100117"><font color=#000080><tt>String</tt></font></a>-Objekts
+verä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ä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ändernden</i> <a href="index_s.html#ixb100545"><font color=#000080><tt>StringBuilder</tt></font></a>-Methoden
+abgefragt und führt dazu, dass - wenn es gesetzt ist - der Pufferinhalt
+vor der Veränderung kopiert und die Ä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ä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öglichkeit bietet, die gespeicherte Zeichenkette nach
+der Instanzierung des Objekts zu verändern, kö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 Ändern eines Strings versehentlich weitere
+Objekte zu ä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ü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änge des Puffers festgehalten werden, müssen im neuen Objekt
+angepasst werden. Dadurch ist auch das Extrahieren von langen Teilzeichenketten
+recht performant. Dasselbe gilt fü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änge ermittelt werden, und durch wiederholten Aufruf von
+<a href="index_c.html#ixb100522"><font color=#000080><tt>charAt</tt></font></a>
+können alle Zeichen nacheinander abgeholt werden. Alternativ
+könnte man auch zunä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äteren Durchlaufen wäre
+dann kein Methodenaufruf mehr erforderlich, sondern die einzelnen
+Array-Elemente kö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ücken zusammensetzen verwenden
+Sie am Besten die Klasse <font color="#000077"><tt>StringBuilder</tt></font>.
+Doch wenn Sie diese Zeichenkette anschließend als Parameter
+oder Rückgabewert übergeben, wird dieser häufig über
+die Methode <font color="#000077"><tt>toString</tt></font> in einen
+äquivalenten <font color="#000077"><tt>String</tt></font> umgewandelt.
+Wird die Zeichenkette anschließend weiter bearbeitet, wird der
+übergebene <font color="#000077"><tt>String</tt></font> anschließend
+wieder in einen <font color="#000077"><tt>StringBuilder</tt></font>
+umgewandelt und so weiter.
+
+<p>
+Sie können sich diese unnötigen Kopieroperationen allerdings
+auch sparen und Ihren Code gleichzeitig wesentlich lesbarer machen,
+indem Sie in diesen Fällen einfach in der Methodensignatur einen
+Parameter vom Typ <font color="#000077"><tt>StringBuilder</tt></font>
+definieren und das Objekt direkt übergeben.
+
+<p>
+Können Sie die Signatur der Methode allerdings nicht ändern
+- etwa, weil die Methode auch mit gewöhnlichen Strings aufgerufen
+werden soll, hält das JDK seit der Version 5 das Interface <a href="index_c.html#ixb100552"><font color=#000080><tt>CharSequence</tt></font></a>
+fü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 übergeben.
+
+<!-- Section -->
+
+<a name="sectlevel3id050002002"></a>
+<h3>50.2.2 Methodenaufrufe </h3>
+
+<p>
+Eine der häufigsten Operationen in objektorientierten Programmiersprachen
+ist der Aufruf einer Methode an einer Klasse oder einem Objekt. Generell
+werden Methodenaufrufe in Java recht performant ausgeführt. Ihr
+Laufzeitverhalten ist jedoch stark von ihrer Signatur und ihren Attributen
+abhängig. <a href="k100314.html#methperformance">Tabelle 50.1</a>
+gibt einen Überblick ü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 ü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ührt, insbesondere bei aktiviertem
+JIT.
+<li>Klassenmethoden werden schneller ausgeführt als Instanzmethoden.
+<li>Die Übergabe von Parametern erfordert zusä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>)
+ü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ü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. überlagert werden sollen. Auch könnte
+man versuchen, verstärkt Klassenmethoden zu verwenden oder zur
+Vermeidung von polymorphen Aufrufen die Vererbungshierachie zu beschrä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ätten aber einen
+starken Einfluss auf das Klassendesign der Anwendung und könnten
+sich leicht an anderer Stelle als Sackgasse herausstellen.
+
+<p>
+Der einzig wirklich allgemeingü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 ü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ät bezüglich
+der Art und Menge der zu speichernden Elemente wird er in vielen Programmen
+ausgiebig verwendet. Bei falschem Einsatz können Vektoren durchaus
+zum Performance-Killer werden, und wir wollen daher einige Hinweise
+zu ihrer Verwendung geben.
+
+<p>
+Zunächst einmal ist der Datenpuffer eines Vektors als Array implementiert.
+Da die Größe von Arrays nach ihrer Initialisierung nicht
+mehr verändert werden kann, erfordert das Einfügen neuer
+Elemente mö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ät</i> und <i>Ladefaktor</i>.
+Die Kapazität gibt an, wie viele Elemente insgesamt aufgenommen
+werden können, also wie groß der interne Puffer ist. Der
+Ladefaktor bestimmt, um wie viele Elemente der interne Puffer erweitert
+wird, wenn beim Einfügen eines neuen Elements nicht mehr ausreichend
+Platz vorhanden ist. Je kleiner die anfängliche Kapazität
+und der Ladefaktor sind, desto häufiger ist beim fortgesetzten
+Einfügen von Elementen ein zeitaufwä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ängliche
+Kapazität von 10 Objekten und der Ladefaktor ist 0. Letzteres
+bedeutet, dass die Kapazitä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ät oder auch beide Werte beim Instanzieren an
+den Konstruktor ü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änglichen Kapazitä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ügung, die anstelle
+von <a href="index_v.html#ixb100120"><font color=#000080><tt>Vector</tt></font></a>
+verwendet werden kö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änge,
+die beim Erweitern des Arrays erforderlich waren. Durch die Vielzahl
+der allozierten Objekte, in denen die Listenelemente und die Zeiger
+gespeichert werden mü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 ä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"> JDK1.1-6.0 </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 übergeben bekommen und
+daraus eine bestimmte Anzahl von Elementen zurü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 Übergabe von 100000 Elementen,
+von denen jeweils die Hälfte zurückgegeben wurden, war das
+Verhä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 < 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 < 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 < 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 < 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 < 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 < 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ügungen und Löschungen
+innerhalb der Liste vorzunehmen, sollte im allgemeinen eine zeigerbasierte
+Implementierung der arraybasierten vorgezogen werden. Während
+es bei letzterer stets erforderlich ist, einen Teil des Arrays umzukopieren,
+wenn ein Element eingefügt oder gelö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ö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ö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über
+dem ungepufferten Zugriff. Die von <a href="index_b.html#ixb100964"><font color=#000080><tt>BufferedWriter</tt></font></a>
+verwendete Standard-Puffergröße von 8 kByte ist in aller
+Regel ausreichend, weitere Vergröß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ü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ü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 (ä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ühren
+keine aufwändige Konvertierung durch, sondern geben je Zeichen
+einfach dessen niederwertige 8 Bit aus. Das spart viel Zeit und fü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ä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ürden. Da der UNICODE-Zeichensatz in den ersten 256 Zeichen
+zum ISO-8859-1-Zeichensatz kompatibel ist, sollten sich für die
+meisten europäischen und angelsä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ßen Datei, bei der zunä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ührungsgeschwindigkeit
+der zweiten Variante um etwa eine Zehnerpotenz ü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 < LINES; ++i) {
+<font color="#555555">006 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> j = 0; j < 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 < LINES; ++i) {
+<font color="#555555">021 </font> <font color="#0000AA">for</font> (<font color="#006699">int</font> j = 0; j < 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 ä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öß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ö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ö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ö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öglichkeit, sie zum Zweck der Pufferung
+zu schachteln. Tatsä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öß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öße und
+Verarbeitungsaufwand werden dann Geschwindigkeiten wie bei gepufferten
+Bytestreams oder höher erzielt. Das folgende Beispiel zeigt,
+wie man mit einem 100 Byte groß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 <= 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ücken von jeweils
+100 Byte ein. Der Rückgabewert von <a href="index_r.html#ixb100984"><font color=#000080><tt>read</tt></font></a>
+gibt die tatsächliche Zahl gelesener Bytes an. Sie entspricht
+normalerweise der Puffergröße, liegt aber beim letzten
+Datenpaket darunter, wenn die Dateigröße nicht zufällig
+ein Vielfaches der Puffergröß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ür ein Java-Programm sicherlich
+ein respektabler Wert ist. Ein wesentlicher Grund ist darin zu suchen,
+dass durch den programmeigenen Puffer ein Groß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ä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änger als das eines mit 10 Elementen.
+<li>Objekte mit aufwändigen Konstruktoren benötigen möglicherweise
+viel Zeit zur Initialisierung. Bei ihnen kann es sinnvoll sein, sie
+zu »recyceln«. Dazu werden sie nach Gebrauch in einer geeigneten
+Datenstruktur gesammelt und können dem nächsten Interessenten
+(alternativ zur Erzeugung eines neuen Objekts) zur Verfügung
+gestellt werden. Vor der Verwendung muss dieser das Objekt natürlich
+geeignet initialisieren.
+<li>Nicht mehr referenzierter Speicher belastet den Garbage Collector
+und erfordert CPU-Zeit, um dem Programm wieder zugeführt werden
+zu können.
+<li>In ungünstigen Fällen kann es sein, dass die VM den
+benötigten Speicher schrittweise in relativ kleinen Stücken
+beim Betriebssystem anfordert. Das kostet unter Umstä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öheren
+Wert einzustellen.
+<li>Große Mengen an temporä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üll erzeugt.
+<li>Werden Referenzen auf Objekte nicht gelö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ührt früher
+oder spä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ötigte Objekte an »lebenden« Referenzen hängen
+(also an Variablen, die im Programm noch benötigt werden). Lebende
+Referenzen sind die lokalen Variablen auf den Stacks aller laufenden
+Threads plus alle statischen Variablen des Programms. Zudem natürlich
+alle Variablen, die indirekt daran hängen. Als Programmierer
+sollte man diesbezü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ö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"> Titel </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100003.html"> Inhalt </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="search.html"> Suchen </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="index.html"> Index </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/index.html" onClick="this.href=getDocIndex()"> DOC </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"> << </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100313.html"> < </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100315.html"> > </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="k100317.html"> >> </a>
+<td width="7%" align=center bgcolor="#DDCC99"><a href="../jdkdocs/api/index.html" onClick="this.href=getApiIndex()"> API </a>
+<td align="right">© 1998, 2007 Guido Krüger & Thomas
+Stark, <a href="http://www.javabuch.de">http://www.javabuch.de</a>
+</table>
+<a name="endofbody"></a>
+</body>
+</html>
|
