374 Stimmen

Wie kann man in Java am besten eine Zeichenkette mit abgegrenzten Elementen erstellen?

Bei der Arbeit in einer Java-Anwendung musste ich kürzlich eine durch Kommata getrennte Liste von Werten zusammenstellen, die ich an einen anderen Webdienst weitergeben wollte, ohne im Voraus zu wissen, wie viele Elemente es sein würden. Das Beste, was mir auf Anhieb einfiel, war so etwas wie dieses:

public String appendWithDelimiter( String original, String addition, String delimiter ) {
    if ( original.equals( "" ) ) {
        return addition;
    } else {
        return original + delimiter + addition;
    }
}

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

Mir ist klar, dass dies nicht besonders effizient ist, da überall Zeichenketten erstellt werden, aber mir ging es mehr um Klarheit als um Optimierung.

In Ruby kann ich stattdessen etwas Ähnliches machen, was sich viel eleganter anfühlt:

parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");

Aber da Java keinen Join-Befehl hat, konnte ich nichts Vergleichbares finden.

Wie lässt sich dies in Java am besten bewerkstelligen?

1voto

Mark B Punkte 154748

Mit Java 5 müssen Sie nicht mehr alle Strings explizit in eine Sammlung oder ein Array packen:

import junit.framework.Assert;
import org.junit.Test;

public class StringUtil
{
    public static String join(String delim, String... strings)
    {
        StringBuilder builder = new StringBuilder();

        if (strings != null)
        {
            for (String str : strings)
            {
                if (builder.length() > 0)
                {
                    builder.append(delim).append(" ");
                }
                builder.append(str);
            }
        }           
        return builder.toString();
    }
    @Test
    public void joinTest()
    {
        Assert.assertEquals("", StringUtil.join(",", null));
        Assert.assertEquals("", StringUtil.join(",", ""));
        Assert.assertEquals("", StringUtil.join(",", new String[0]));
        Assert.assertEquals("test", StringUtil.join(",", "test"));
        Assert.assertEquals("foo, bar", StringUtil.join(",", "foo", "bar"));
        Assert.assertEquals("foo, bar, x", StringUtil.join(",", "foo", "bar", "x"));
    }
}

1voto

agnul Punkte 11830

Warum machen Sie in Java nicht das Gleiche wie in Ruby, d.h. Sie erstellen die vom Trennzeichen getrennte Zeichenkette erst, nachdem Sie alle Teile zum Array hinzugefügt haben?

ArrayList<String> parms = new ArrayList<String>();
if (someCondition) parms.add("someString");
if (anotherCondition) parms.add("someOtherString");
// ...
String sep = ""; StringBuffer b = new StringBuffer();
for (String p: parms) {
    b.append(sep);
    b.append(p);
    sep = "yourDelimiter";
}

Möglicherweise möchten Sie diese for-Schleife in einer separaten Helper-Methode zu verschieben, und auch StringBuilder anstelle von StringBuffer verwenden...

Editar : Die Reihenfolge der Anhänge wurde festgelegt.

1voto

newdayrising Punkte 3722

Sie sollten wahrscheinlich eine StringBuilder mit dem append Methode, um Ihr Ergebnis zu konstruieren, aber ansonsten ist dies die beste Lösung, die Java zu bieten hat.

0voto

user13276 Punkte 4853

Es gibt also ein paar Dinge, die Sie tun können, um das Gefühl zu bekommen, das Sie offenbar suchen:

1) Erweitern Sie die Klasse List - und fügen Sie ihr die join-Methode hinzu. Die join-Methode würde einfach die Arbeit der Verkettung und des Hinzufügens des Trennzeichens übernehmen (das ein Parameter für die join-Methode sein könnte)

2) Es sieht so aus, als ob Java 7 Erweiterungsmethoden zu Java hinzufügt - was Ihnen erlaubt, eine bestimmte Methode an eine Klasse anzuhängen: Sie könnten also diese Join-Methode schreiben und sie als Erweiterungsmethode zu List oder sogar zu Collection hinzufügen.

Lösung 1 ist wahrscheinlich die einzige realistische Lösung, da Java 7 noch nicht auf dem Markt ist :) Aber es sollte gut funktionieren.

Um diese beiden Methoden zu verwenden, fügen Sie einfach alle Elemente wie gewohnt zur Liste oder Sammlung hinzu und rufen dann die neue benutzerdefinierte Methode auf, um sie zu verbinden.

0voto

dfa Punkte 110809

Mit Dollar ist so einfach wie Tippen:

String joined = $(aCollection).join(",");

NB: Es funktioniert auch für Array und andere Datentypen

Umsetzung

Intern wird ein sehr geschickter Trick angewendet:

@Override
public String join(String separator) {
    Separator sep = new Separator(separator);
    StringBuilder sb = new StringBuilder();

    for (T item : iterable) {
        sb.append(sep).append(item);
    }

    return sb.toString();
}

die Klasse Separator gibt nur beim ersten Aufruf die leere Zeichenkette zurück, danach wird das Trennzeichen zurückgegeben:

class Separator {

    private final String separator;
    private boolean wasCalled;

    public Separator(String separator) {
        this.separator = separator;
        this.wasCalled = false;
    }

    @Override
    public String toString() {
        if (!wasCalled) {
            wasCalled = true;
            return "";
        } else {
            return separator;
        }
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X