Frage

Ich iteriere durch eine HashMap (siehe meine frühere Frage für weitere Einzelheiten) und Erstellen einer Zeichenfolge, die aus den in der Karte enthaltenen Daten besteht.Für jeden Artikel werde ich eine neue Zeile haben, aber für den allerletzten Artikel möchte ich keine neue Zeile.Wie kann ich das erreichen?Ich dachte, ich könnte irgendwie überprüfen, ob der Eintrag der letzte ist oder nicht, aber ich bin mir nicht sicher, wie ich das eigentlich machen soll.

Danke!

War es hilfreich?

Lösung

ändern Sie Ihren Denkprozess von „anhängen eine Linie bricht alle, aber das letzte Mal“ auf „voranstellen, eine Linie brechen alle, aber das erste Mal“:

boolean first = true;
StringBuilder builder = new StringBuilder();

for (Map.Entry<MyClass.Key,String> entry : data.entrySet()) {
    if (first) {
        first = false;
    } else {
        builder.append("\n"); // Or whatever break you want
    }
    builder.append(entry.key())
           .append(": ")
           .append(entry.value());
}

Andere Tipps

ein Verfahren (mit Entschuldigungen zu Jon Skeet für einen Teil seines Java-Code zu leihen):

StringBuilder result = new StringBuilder();

string newline = "";  
for (Map.Entry<MyClass.Key,String> entry : data.entrySet())
{
    result.append(newline)
       .append(entry.key())
       .append(": ")
       .append(entry.value());

    newline = "\n";
}

Was ist das?

StringBuilder result = new StringBuilder();

for(Map.Entry<MyClass.Key,String> entry : data.entrySet())
{
    builder.append(entry.key())
       .append(": ")
       .append(entry.value())
       .append("\n");
}

return builder.substring(0, builder.length()-1);

Obligatorische Entschuldigungen und dank sowohl Jon und Joel für „Borgen“ von ihrem Beispiel.

Ususally für diese Art von Dingen, die ich verwende Apache-Commons-lang StringUtils # join . Zwar ist es nicht wirklich schwer ist, alle diese Arten von Utility-Funktionen zu schreiben, ist es immer besser zu bestehenden bewährten Bibliotheken wiederverwenden. Apache-Commons so voll von nützlichen Sachen ist!

Wenn Sie Iterator verwenden, anstatt für ... jeder Code könnte wie folgt aussehen:

StringBuilder builder = new StringBuilder();

Iterator<Map.Entry<MyClass.Key, String>> it = data.entrySet().iterator();

while (it.hasNext()) {
    Map.Entry<MyClass.Key, String> entry = it.next();

    builder.append(entry.key())
    .append(": ")
    .append(entry.value());

    if (it.hasNext()) {
        builder.append("\n");
    }
}

Dies ist wahrscheinlich ein besseres Beispiel ...

final StringBuilder buf = new StringBuilder();
final String separator = System.getProperty("line.separator"); // Platform new line
for (Map.Entry<MyClass.Key,String> entry: data.entrySet()) {
    builder.append(entry.key())
       .append(": ")
       .append(entry.value())
       .append(separator);
}
// Remove the last separator and return a string to use.
// N.b. this is likely as efficient as just using builder.toString() 
// which would also copy the buffer, except we have 1 char less 
// (i.e. '\n').
final String toUse = builder.substring(0, builder.length()-separator.length()-1);

Hier ist meine prägnante Version, die die Länge Eigenschaft anstelle einer zusätzlichen Variable String verwendet:

StringBuilder builder = new StringBuilder();

for (Map.Entry<MyClass.Key,String> entry : data.entrySet())
{
    builder.append(builder.length() > 0 ? "\n" : "")
           .append(entry.key())
           .append(": ")
           .append(entry.value());
}

(Apologies und dank sowohl Jon und Joel für "Leihen" von ihren Beispielen.)

Eine Lösung ist eine benutzerdefinierte Wrapper Stringbuilder zu erstellen. Es kann nicht verlängert werden, so dass ein Wrapper erforderlich ist.

public class CustomStringBuilder {

final String separator = System.getProperty("line.separator");

private StringBuilder builder = new StringBuilder();

public CustomStringBuilder appendLine(String str){
    builder.append(str + separator);
    return this;
}

public CustomStringBuilder append(String str){
    builder.append(str);
    return this;
}

public String toString() {
    return this.builder.toString();
}

}

Die Umsetzung wie so:

CustomStringBuilder builder = new CustomStringBuilder();

//iterate over as needed, but a wrapper to StringBuilder with new line features.

builder.appendLine("data goes here");
return builder.toString();

Dies hat einige Nachteile haben:

  • Das Schreiben von Code, dass ist in der Regel nicht "Domain / business" centric
  • Nicht mit Open-Source-Standardlösung wie: StringUtils.join
  • gezwungen, eine Klasse zu erhalten, die eine JDK Klasse umschließt, die letzte und damit ist Updates langfristig erforderlich.

ging ich mit der StringUtils.join Lösung über Sammlungen für Iterieren und sogar leichte Build-Methode Muster Aufbau im Code.

Ihre foreach-Schleife geht, um durch die Datei Unter der Annahme, nur eine neue Zeile zu jeder Zeichenfolge hinzuzufügen und die letzte neue Zeile, wenn die Schleife beendet zu entfernen.

Nicht sicher, ob dies die beste, aber es ist die einfachere Art und Weise zu tun:

Schleife durch alle Werte und hängen die \ n normalerweise im Stringbuffer. Dann tun so etwas wie dieses

sb.setLength(sb.length()-1); 

Dies ist, wo ein Verfahren beizutreten, ergänzen Split, würde sich als nützlich, denn dann könnte man einfach alle Elemente verbinden, um eine neue Zeile als Trennzeichen verwenden, und natürlich ist es nicht eine neue Zeile an das Ende anhängen des Ergebnisses; das ist, wie ich es in verschiedenen Skriptsprachen (Javascript, PHP, usw.).

Wenn Sie Klasse Separator , Sie tun können,

StringBuilder buf = new StringBuilder();
Separator separator = new Separator("\n");
for (Map.Entry<MyClass.Key,String> entry: data.entrySet()) {
    builder.append(separator)
       .append(entry.key())
       .append(": ")
       .append(entry.value());
}

Die Trenn druckt in leeren String auf dem ersten Gebrauch, und der Separator auf alle nachfolgenden Verwendungen.

Lassen Bibliotheken dies für Sie tun.

import com.sun.deploy.util.StringUtils;

sowie viele andere haben StringUtils, die eine Join-Methode hat. Sie können dies in einer Zeile ein:

StringUtils.join(list, DELIMITER);

Aber für mehr Kontext, hier ist, wie Sie es mit einem hashmap tun könnten.

public static String getDelimitatedData(HashMap<String, String> data) {
    final String DELIMITER = "\n"; //Should make this a variable
    ArrayList<String> entries = new ArrayList<>();

    for (Map.Entry<String, String> entry : data.entrySet()) {
        entries.add(entry.getKey() + ": " + entry.getValue());
    }

    return StringUtils.join(entries, DELIMITER);
}

Verwenden Sie die JDK-APIs zum Verknüpfen von Zeichenfolgen:

String result = data.stream()
    .map((k,v) -> String.format("%s : %s", k, v)
    .collect(Collectors.joining("\n"));
scroll top