Med 1.4 mener jeg bare JDK1.4 :) Her er en anden en med StringTokenizer:
import java.util.*; class Replace { public static void main(String[] args) { StringTokenizer s = new StringTokenizer(\"Her er dete som du vil have\",\" ,.:;!?\",true); String n=\"\"; while (s.hasMoreTokens()) { String t=s.nextToken(); if (t.equals(\"dete\")) { t=\"dette\"; } if (t.equals(\"ombusmand\")) { t=\"ombudsmand\"; }
String er immutabel og skal IKKE bruges til det du gør, det er håbløst langsomt.
Denne løsning er bedre og hurtigere.
import java.util.*; class Replace { public static void main(String[] args) { StringTokenizer s = new StringTokenizer(\"Her er dete som du vil have\",\" ,.:;!?\",true); StringBuffer n=new StringBuffer(); while (s.hasMoreTokens()) { String t=s.nextToken(); if (t.equals(\"dete\")) { t=\"dette\"; } if (t.equals(\"ombusmand\")) { t=\"ombudsmand\"; }
Hvis hr. Bloch påstår at forskellen ER 1:100 ved han vidst ikke hvad han snakker om. Den kan være 1:10 eller 1:1000 eller.... afhængig af mængden af tekst. Men det er jo nok bare et eksempel han kommer med. Men til store ting skal man da bruge StringBuffer - naturligvis.
Kan I så........... Man kan da heller ikke lade jer være alene et øjeblik.
Jeg tog lige og kompilerede følgende program:
String a = \"a\"; int f = 4; String c = \"c\"; String x = null;
// To slags concat. x = a + f + c; x = new StringBuffer().append(a).append(f).append(c).toString();
Hvilken en af dem tror I er bedst ??
Her er et uddrag af bytecoden: --- x = a + f + c; 11 new #4 <Class java.lang.StringBuffer> 14 dup 15 invokespecial #5 <Method java.lang.StringBuffer()> 18 aload_1 19 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)> 22 iload_2 23 invokevirtual #7 <Method java.lang.StringBuffer append(int)> 26 aload_3 27 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)> 30 invokevirtual #8 <Method java.lang.String toString()> 33 astore 4 --- x = new StringBuffer().append(a).append(f).append(c).toString(); 35 new #4 <Class java.lang.StringBuffer> 38 dup 39 invokespecial #5 <Method java.lang.StringBuffer()> 42 aload_1 43 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)> 46 iload_2 47 invokevirtual #7 <Method java.lang.StringBuffer append(int)> 50 aload_3 51 invokevirtual #6 <Method java.lang.StringBuffer append(java.lang.String)> 54 invokevirtual #8 <Method java.lang.String toString()> 57 astore 4
Jeg har også læst Joshua Blochs bog, men han bruger altså en dårlig compiler, som f.eks. suns egen :-) Spøg til side. Jeg brugte selv Sun 1.3.1 Win32 udgaven.
Der er andre situationer, hvor Bloch har ret i sit punkt, men det er ikke nødvendigvis til daglig.
Et godt råd til jer fra mig (Helt gratis).
Lad være med at kode noget fordi I tror det giver bedre performance. I ødelægger oftere design og forståelighed frem for at lade performance ligge og finde ud af hvor problemerne er. Jeg kender ingen, som har kunnet forudse alle performancebottlenecks på design time, men jeg har set mange brænde meget krudt af uden resultat.
Hvilket jo blot viser, at i et udtryk med String kan compileren bruge StringBuffer, men når det aktuelle udtryk er færdigt, konverteres det til String, som sig hør og bør. Og det er \"dyrt\", ja, hvis man ellers behøver bekymre sig om det.
Hvis man har mere end de to ord \"dete\" og \"ombusmand\" skal man jo nok heller ikke bare bruge lineær søgning, men f.eks. en HashMap. Men alt det kan man jo vente med til man ved om det er nødvendigt (hvis refactoring ikke allerede var opfundet, ville jeg gøre det, haha) - så jeg er grundlæggende enig med logical. Og det morsomme ved det hele er jo, at jeg også er grundlæggende enig med disky. Men jeg gider bare ikke skrive så meget i et lille svar om noget helt andet :) ...ja, og så gør jeg det alligevel....
Det gode råd, lyder bestemt som noget jeg hørte på java one, det var vel ikke hr. Bloch :-)
Og hvis du har:
String a=\"hej \"; a+=\"med \"; a+=\"dig \";
f.eks. med kode ind imellem hvordan ser det så ud i forhold til at bruge Stringbuffer ?
Jeg vil give dig og Bloch ret, normalt er det dumt at spilde tid på optimering, men lige i String vs. StringBuffer\'s tilfælde er de rent dovenskab ikke at gøre det. Da StringBuffer i 99 % er hurtigere og aldrig langsommere (ved concatenering)
disky>> Jeg har nu helt mine egne erfaringer på det område, og kunne give det råd endda før J1. Jeg plejer sjældent at genbruge andres råd, hvis jeg ikke selv har kigget problemstillingen igennem (Jeg vil se med fingrene).
Eksemplet ovenpå var et eksempel på, at det ikke altid er til at gennemskue hvad der sker, hvilket betyder at udtryk som \"Man bruger ALTID StringBuffer hvis der skal ændres det mindste i en String. Hvis ikke er man en slam koder\" måske ikke har sin berettigelse. For så er der mange også hos javasoft som er slam kodere :-) (Og så mig selv for øvrigt)
Du er lidt for hurtig ude med riven, selv om du har ret i noget af det du siger. Bloch har et eksempel scenario, hvor han har en faktor 90 på hans maskine ved 100 iterationer med en 80 karakters string. Den er ikke direkte sammenlignelig på min maskine f.eks. Så lad være med at citere noget halvt.
Han har iøvrigt skrevet en enkelt interessant linie: The morale is simple: Don\'t use the string concatenation operator to combine MORE THAN A FEW strings unless PERFORMANCE IS IRRELEVANT.
Og mht til ALTID at bruge en StringBuffer, skriver du sådan her:
int i = 42; System.out.println(\"Indholdet er \" + i + \"tilfældigvis\");
eller
int i = 42; System.out.println(new StringBuffer(\"Indholdet er \").append(i).append(\"tilfældigvis\").toString());
out.println(\"Alt min tekst omkring dete java spørgsmål er sendt til vores ombusmand\"); out.flush(); System.out.println(sw.toString());
rep har en intern sorted hashmap, og write parser ind (lidt ligesom StringTokenizer), og laver lookup i hashmap før indhold skrives videre til næste writer.
okay altid var måske lidt ofte. (overdrivelse fremmer forståelsen)
Men hvad gør du så hvis du f.eks. skal appende ting til strengen lidt efter lidt altså hvor der foregår anden programmering ind i mellem.
Det er helt korrekt at
int i = 42; System.out.println(\"Indholdet er \" + i + \"tilfældigvis\");
og
int i = 42; System.out.println(new StringBuffer(\"Indholdet er \").append(i).append(\"tilfældigvis\").toString());
giver det samme i bytekoden, det står jo i api\'en.
Problemmet er at skal men bag efter tilføje noget mere til strengen på baggrund af noget andet, så skal String udgaven først instantiere en StringBuffer med String som indhold, så appende derefter toString(), næste gang igen instantiere en StringBuffer, så appende så toString() igen osv.
Så bare man skal tilføje noget til en streng to gange, er det langsommere end at bruge StringBuffer.
De eneste tidspunkter jeg ikke bruger StringBuffer er:
1. når jeg generere en String i et huk 2. eksempler til Eksperten 3. jeg eksperimenterer.
Men til kode der skal bruger bruger jeg altid StringBuffer.
En helt anden ting den ReplacementWriter du har lavet er det en man må se ?
Nej :-) Det er ikke en ren open source forretning :-)
Men generelle ideer bag ved extends FilterWriter private Map map = new TreeMap(); private String delimiters = \" \\n\\t\\r.,:;!\"#¤%&/()=?+-_\'\";
overskriv write metoder til at se om der er en token, hvis nej gem content. Hvis ja, hvis vi har en matching key, super.write(value) eller super.write(key)
Her er en metode som bare gør det, uden så meget snak.. :)
Udskifter alle foremomster af \'from\' med \'to\' i Strengen Str:
public static String replace(String str, String from, String to)
{ StringBuffer stringBuf = new StringBuffer(str); String returnSt = new String(); int i; int e; i = 0; e = str.indexOf(from,i); while (e!=-1) { stringBuf.replace(e, e+from.length() , to); i = e+to.length(); str = new String(stringBuf); e=str.indexOf(from, i); } returnSt = new String(stringBuf); return returnSt; }
vh 49152
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.