Strings hochzählen

Diskutiere Strings hochzählen im Java Basics - Anfänger-Themen Bereich.
K

Krischan

Hallo,

ich habe gerade eine Übungsaufgabe, bei der ich nicht weiterkomme.

Das Programm soll nach zwei Wörter fragen und diese dann in einer Zeile ausgeben. Getrennt sollen die Wörter mit Punkten sein. Die ausgegebene Zeichenlänge soll 30.
Beispiel: Hallo.....................Welt

Hier mein bisher geschriebener Code:

import java.util.Scanner;
public class test {

public static void main(String[] args) {

{
Scanner scan = new Scanner( System.in );
int text1, text2, text;
String string1, string2, gesamt, punkt;
punkt = (".");



System.out.println("Geben sie das erste Wort ein");
string1 = scan.nextLine();
text1 = string1.length();

System.out.println("Geben sie das zweite Wort ein");
string2 = scan.nextLine();
text2 = string2.length();

gesamt = string1 + string2;
text = gesamt.length();

while (text <= 30)
Hier weiß ich einfach nicht wie ich den String "punkt" hochzählen soll UND wie ich ihn dann wieder zwischen string 1 und string 2 plaziere

System.out.println(gesamt);


}


}

}
 
X

Xyz1

Bevor Rückfragen kommen, nein das löst man nicht funktional:

Java:
	private static String c(String a, String b) {
		while ((a + b).length() < 30)
			a += '.';
		return a + b;
	}

	public static void main(String[] args) throws Exception {
		System.out.println(c("Hallo", "du"));
	}
 
K

kneitzel

Bevor Rückfragen kommen, nein das löst man nicht funktional:

Java:
    private static String c(String a, String b) {
        while ((a + b).length() < 30)
            a += '.';
        return a + b;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(c("Hallo", "du"));
    }
Also diese Lösung halte ich für wenig optimal, da Du hier sehr viele Strings erstellst durch dieses zusammenfügen von Strings.

Das kann man stark vermindern, indem man halt einmal die benötigte Anzahl an Punkten berechnet (Dann entfällt das a+b in jedem Durchlauf) und dann ist hier auch der StringBuilder angebracht.

Oder eine andere Alternative ist String.format - damit kann man eine Zeichenkette aus Leerzeichen der gewünschten Länge erstellen um dann halt die Leerzeichen durch . zu ersetzen:
Java:
        String a = "Hallo";
        String b = "Welt!";
        System.out.println(a + String.format("%" + (30-a.length()-b.length()) +"s", "").replace(" ", ".") + b);
 
mrBrown

mrBrown

Der Compiler optimiert das weg, Du wirst keinen Geschwindigkeitsunterschied feststellen
Unsinn. Eben das optimiert der nicht weg.

Und da du mir nicht glauben wirst, hier sind Benchmarkergebnisse (length ist die Länge der beiden Strings):

Code:
Benchmark                        (length)  Mode  Cnt      Score    Error  Units
StringBenchmark.dumb                    1  avgt   10   1176,242 ± 28,076  ns/op
StringBenchmark.dumb                    3  avgt   10    955,941 ±  5,691  ns/op
StringBenchmark.dumb                   10  avgt   10    446,105 ±  1,126  ns/op
StringBenchmark.lengthExtracted         1  avgt   10    495,656 ±  3,801  ns/op
StringBenchmark.lengthExtracted         3  avgt   10    414,179 ±  1,362  ns/op
StringBenchmark.lengthExtracted        10  avgt   10    186,987 ±  1,449  ns/op
StringBenchmark.stringBuilder           1  avgt   10    134,628 ±  6,827  ns/op
StringBenchmark.stringBuilder           3  avgt   10    129,366 ±  5,816  ns/op
StringBenchmark.stringBuilder          10  avgt   10    102,463 ±  1,721  ns/op

StringBenchmark.format                  1  avgt   10   1029,457 ± 15,137  ns/op
StringBenchmark.format                  3  avgt   10    944,531 ±  7,513  ns/op
StringBenchmark.format                 10  avgt   10    884,033 ±  6,142  ns/op
StringBenchmark.streams                 1  avgt   10  13375,974 ± 76,527  ns/op
StringBenchmark.streams                 3  avgt   10  10537,755 ± 53,091  ns/op
StringBenchmark.streams                10  avgt   10   3098,467 ± 20,582  ns/op

StringBenchmark.repeat                  1  avgt   10     58,861 ±  0,791  ns/op
StringBenchmark.repeat                  3  avgt   10     50,555 ±  0,110  ns/op
StringBenchmark.repeat                 10  avgt   10     48,398 ±  1,125  ns/op
dumb ist deine Version, lengthExtracted ist nur das entfernen der Konkatenation im Schleifenkopf, stringBuilder das ganze mit StringBuilder statt direkter Konkatenation.

format und streams sind die anderen beiden Varianten aus diesem Thread (die nicht den Anspruch hatten, irgendwie performant zu sein).

repeat ist die optimale Variante mit String.repeat.

Java:
public String lengthExtracted(String a, String b) {
    while (a.length() + b.length() < 30) {
        a += '.';
    }
    return a + b;
}

Java:
public String stringBuilder(String a, String b) {
    StringBuilder builder = new StringBuilder(a);

    while (builder.length() + b.length() < 30) {
        builder.append(".");
    }
    return builder.append(b).toString();
}

Java:
public String repeat(String a, String b) {
    return a + ".".repeat(30 - a.length() - b.length()) + b;
}
 
mrBrown

mrBrown

nicht in einem Benchmark vielleicht - ändert aber alles nichts daran dass das nicht der Bottelneck ist. :rolleyes:
Er optimiert es nie weg. Ja, Bottleneck wird es nicht sein, das war aber auch nicht deine Aussage - deine Aussage war "Der Compiler optimiert das weg", und das ist schlicht falsch.
 
K

kneitzel

Das mit der Optimierung war auch in meinen Augen unwahrscheinlich, denn in der Schleife erzeugt a=a+"."; ja immer eine neue String Instanz. Für uns ist die Operation relativ einfach und übersichtlich, aber das ist für den Compiler erst einmal einfach eine komplett neue Instanz. Und diese Instanz wird dann in der Bedingung wieder benutzt, aber hier ist auch wieder eine Operation beteiligt, die eine komplett neue Instanz erzeugt um da dann length() aufzurufen.

Also insgesamt nichts, was einfach zu optimieren ist. Das lässt sich nur mit tiefgreifendem Wissen zu String und der Implementierung von String optimieren....

Und was ich meine ist: Anfänger sollen gewisse Dinge von Anfang an richtig lernen. Und da gibt es gewisse Dinge, die aus meiner Sicht schnell gelehrt werden müssten. Das sind dann so Punkte wie z.B. schnell hin zur Objektorientierten Denkweise (Sorry, das geht doch nicht anders. Mit anderen Instanzen wird ja auch schon gearbeitet!) und geht dann auch hin zu gewissen Dingen, die nicht gemacht werden sollten. Das sind dann so Dinge wie Strings zusammen basteln für SQL Abfragen statt Nutzung von Parametern oder eben dieses generelle, massive Zusammenbasteln von Strings.

Denn es geht hier nicht nur um die Performance bei der Ausführung, sondern es gibt ja noch deutlich mehr Dinge: Der GC muss mehr machen, mehr Speicher wird verbraucht, ....

Aber ok, es ist hier wohl auch immer die Frage, welches Ziel man verfolgt: Will ich wirkliche Software Entwickler oder will ich nur ein wenig "rumspielen". In Schule und Studium wird halt oft kein wirkliches Ziel verfolgt, bzw. dies scheint sehr willkürlich. Aber das ist ein generelles Thema, das ich hier nicht anfangen will (Aber da gibt es ja auch im Netz genug zu. Universitäten beklagen ja oft genug, dass die Schule unzureichend auf das Studium vorbereitet und so ....).
 
X

Xyz1

Ändert alles nichts daran, dass man das so, vielleicht noch unter Einsatz eines StringBuilder s, genau so machen sollte - und nicht anders.
 
K

kneitzel

Ändert alles nichts daran, dass man das so, vielleicht noch unter Einsatz eines StringBuilder s, genau so machen sollte - und nicht anders.
Das ist Deine Meinung. Meiner Meinung nach sollte man sich eine Problematik genauer ansehen um diese dann zielführend zu lösen.

Und wenn es einen direkten Weg gibt, dann würde ich immer diesen nehmen. Direkter Weg ist hier aus meiner Sicht eben das klare Verständnis, dass die Anzahl der "." zwischen den beiden Strings genau 30 - Länge A - Länge B ist. Und dann baue ich den String genau so auf.
Das ist eine Lösung, die ich der Schleife vorziehen würde zumal diese Lösung einfach und klar erkennbar ist.

Und von einem Software Entwickler erwarte ich, dass er Lösungen einfach aufbaut. Wieso ständig Strings zusammensetzen wenn es nur um die Länge geht? Das (a+b).length führt unnötige Operationen aus. KISS Prinzip ist hier aus meiner Sicht nicht eingehalten.

Daher meine Sicht:
- Ist es eine valide Lösung für einen Anfänger: Ja
- Ist es die Musterlösung, die zeigt: So sollte es aussehen? Klares Nein.

Lösungen wie mein String.format mit replace sind natürlich auch keine Musterlösung (Aber valide, repeat gibt es in Java 8 noch nicht? Zumindest sehe ich das hier nicht.)
Aber meine Musterlösung würde den StringBuilder mit einfließen lassen alleine um diese Problematik schon einmal erwähnt zu haben. Eine zweite Lösung, die ich als valide vorstellen würde, würde in einer Schleife von 1...n die "." zusammen setzen.

Aber das ist natürlich nur meine Meinung und es steht jede frei, seine eigene Meinung zu haben.
 
mrBrown

mrBrown

Ändert alles nichts daran, dass man das so, vielleicht noch unter Einsatz eines StringBuilder s, genau so machen sollte - und nicht anders.
Ja, ist auch wirklich absolut nicht zu empfehlen, einfach die Methode zu nehmen, die genau für diesen Fall schon existiert und die deutlich performanter ist... \s
 
mrBrown

mrBrown

Lösungen wie mein String.format mit replace sind natürlich auch keine Musterlösung (Aber valide, repeat gibt es in Java 8 noch nicht? Zumindest sehe ich das hier nicht.)
Ja, repeat kam mit Java 11 :)

Die Lösung mit format führt allerdings zu Fehlern, wenn die ursprünglichen Strings Leerzeichen enthalten ;)
 
K

kneitzel

Nei
Ja, repeat kam mit Java 11 :)

Die Lösung mit format führt allerdings zu Fehlern, wenn die ursprünglichen Strings Leerzeichen enthalten ;)
Daher ist das replace ja nur auf dem erzeugten String. Die Variablen (a und b) werden nicht behandelt.

Somit kann da drin sein was will, auch Leerzeichen.
 
mihe7

mihe7

Und da du mir nicht glauben wirst, hier sind Benchmarkergebnisse (length ist die Länge der beiden Strings):
Und hier der Code dazu:
Java:
System.out.println("Benchmark                        (length)  Mode  Cnt      Score    Error  Units");
System.out.println("StringBenchmark.dumb                    1  avgt   10   1176,242 ± 28,076  ns/op");
...
ROFL :p
 
mrBrown

mrBrown

Natürlich erst noch mit StringBuilder zusammengebaut, damit’s effizienter wird.
 
Thema: 

Strings hochzählen

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben