Java: Funktion für Arrays wie PHPs join ()?

259

Ich möchte mich String[]mit einem Klebeband verbinden. Gibt es dafür eine Funktion?

Nick Heiner
quelle
7
In Java 8 ist diese Funktionalität sofort verfügbar. Ich empfehle dem Leser, durch die Antwort von @Marek Gregor zu scrollen (und sie zu verbessern ..)
Stav

Antworten:

307

Ab Java8 ist die Verwendung möglich String.join().

String.join(", ", new String[]{"Hello", "World", "!"})

Erzeugt:

Hello, World, !

Andernfalls verfügt Apache Commons Lang über eine StringUtilsKlasse mit einer joinFunktion, die Arrays zu a zusammenfügt String.

Beispielsweise:

StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

Erzeugt Folgendes String:

Hello, World, !
Coobird
quelle
7
Zum Nutzen der Leute, die nach dieser Antwort suchen, sollte wahrscheinlich beachtet werden, dass dies auch das Äquivalent eines Perl-Joins ist.
k-den
3
es sagt, dass es für mich undefiniert ist
Ninjaxor
@Ninjaxor 1. commons-lang * jar muss sich im Klassenpfad befinden 2. import org.apache.commons.lang3.StringUtils;
Peter - Wiedereinstellung Monica
9
Ich würde empfehlen, diese Antwort zu bearbeiten, um einen Verweis auf die String.join()in Java 8 eingeführte neue Methode anzuhängen . Auf diese Weise wird die große Anzahl von Personen, die diese akzeptierte Antwort lesen, von diesem Wissen profitieren. Derzeit ist die Antwort mit der höchsten Stimmenzahl, die diese Tatsache erwähnt, unten ziemlich verloren ...
Duncan Jones
1
Es ist erwähnenswert, dass String.join()dies nur für List<CharSequence>oder CharSequence[]Elemente funktionieren würde .
Enigo
71

Wenn Sie nach dem suchen, was Sie in Android verwenden können, ist es:

String android.text.TextUtils.join(CharSequence delimiter, Object[] tokens)

beispielsweise:

String joined = TextUtils.join(";", MyStringArray);
Noah
quelle
2
Dies ist eindeutig die beste Antwort für alle Android-Versionen, da Java 8 nur in Kürze auf Android verfügbar ist. Diese Lösung verwendet die eingebauten Android-Bibliotheken, anstatt diese albernen "enthalten eine riesige Bibliothek, um eine Aktion auszuführen" -Lösungen.
LukeStoneHm
Es ist September 2017, Java 8 für Android ist noch weit weg. Danke für diese Antwort!
Aenadon
53

Sie könnten eine solche Funktion leicht in etwa zehn Codezeilen schreiben:

String combine(String[] s, String glue)
{
  int k = s.length;
  if ( k == 0 )
  {
    return null;
  }
  StringBuilder out = new StringBuilder();
  out.append( s[0] );
  for ( int x=1; x < k; ++x )
  {
    out.append(glue).append(s[x]);
  }
  return out.toString();
}
Jay
quelle
35
Gute Praxis Ihrer Meinung nach ... es gibt keinen universellen Standard für solche Dinge.
Phoebus
24
Aber wenn ich geschweifte Klammern eingefügt hätte, hätte das zwei weitere Codezeilen hinzugefügt, und ich hätte nicht behaupten können, dies in 11 Zeilen getan zu haben!
Jay
8
Das Problem ist, wenn Sie nach einer Weile oder jemand anderem in Eile eine weitere Zeile hinzufügen, wenn / für ohne Klammern; oder löschen Sie return null nach if (k == 0), was in einigen Fällen kompiliert wird, aber falsch ist. Dann ist es besser, eine zusätzliche Linie für diese schließende Klammer zu opfern (die Öffnung kann gleich bleiben, wenn / für Linie).
Mailand
16
Ich finde es großartig, dass die meisten Sprachen solche Funktionen in ihren Kern packen, die Java-Community jedoch alle dazu ermutigt, das Rad neu zu erfinden.
John Strickler
33
11 Zeilen? Bah! Ich kann es in 1 tun! Entfernen Sie einfach alle Zeilenumbruchzeichen in der Quelldatei.
Thomas Eding
25

Ein kleiner Mod anstelle von substring ():

//join(String array,delimiter)
public static String join(String r[],String d)
{
        if (r.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        int i;
        for(i=0;i<r.length-1;i++){
            sb.append(r[i]);
            sb.append(d);
        }
        sb.append(r[i]);
        return sb.toString();
}
Everlasto
quelle
Abgestimmt, weil Sie keine Bibliothek hinzufügen müssen.
Givanse
10
Zeile 7: Ist es besser, wenn Sie sie jeweils .append()zweimal verwenden, Stringanstatt sie zu verketten und dann an den Builder anzuhängen?
Talha Ahmed Khan
18

Wie bei vielen Fragen in letzter Zeit hilft Java 8:


Java 8 hat eine neue statische Methode hinzugefügt, java.lang.Stringdie genau das tut, was Sie wollen:

public static String join(CharSequence delimeter, CharSequence... elements);

Es benutzen:

String s = String.join(", ", new String[] {"Hello", "World", "!"});

Ergebnisse in:

"Hello, World, !"
icza
quelle
14

Die Bibliothek von Google Guava verfügt ebenfalls über diese Funktion . Sie können das Beispiel String [] auch in der API sehen.

Achten Sie, wie bereits in der API beschrieben, auf die Unveränderlichkeit der Builder-Methoden.

Es kann eine Reihe von Objekten akzeptieren, sodass es in Ihrem Fall funktioniert. In meiner vorherigen Erfahrung habe ich versucht, mich einem Stapel anzuschließen, der iterierbar ist und gut funktioniert.

Probe von mir:

Deque<String> nameStack = new ArrayDeque<>();
nameStack.push("a coder");
nameStack.push("i am");
System.out.println("|" + Joiner.on(' ').skipNulls().join(nameStack) + "|");

druckt aus: |i am a coder|

Bertie
quelle
9

Gegeben:

String[] a = new String[] { "Hello", "World", "!" };

Dann als Alternative zu Coobirds Antwort, wo der Kleber "," ist:

Arrays.asList(a).toString().replaceAll("^\\[|\\]$", "")

Oder um mit einer anderen Zeichenfolge zu verketten, z. B. "& amp;".

Arrays.asList(a).toString().replaceAll(", ", " &amp; ").replaceAll("^\\[|\\]$", "")

Dies funktioniert jedoch NUR, wenn Sie wissen, dass die Werte im Array oder in der Liste NICHT die Zeichenfolge "," enthalten.

Rob bei TVSeries.com
quelle
Arrays.asList(a).toString()arbeitete für das, was ich tun wollte
Solomon Ucko
9

Wenn Sie das Spring Framework verwenden , haben Sie die StringUtils- Klasse:

import static org.springframework.util.StringUtils.arrayToDelimitedString;

arrayToDelimitedString(new String[] {"A", "B", "C"}, "\n");
devstopfix
quelle
8

Nicht im Kern, nein. Eine Suche nach "Java Array Join String Glue" gibt Ihnen jedoch einige Code-Schnipsel, wie Sie dies erreichen können.

z.B

public static String join(Collection s, String delimiter) {
    StringBuffer buffer = new StringBuffer();
    Iterator iter = s.iterator();
    while (iter.hasNext()) {
        buffer.append(iter.next());
        if (iter.hasNext()) {
            buffer.append(delimiter);
        }
    }
    return buffer.toString();
}

quelle
2
Verwenden Sie StringBuilder (nicht threadsicher) anstelle von StringBuffer (threadsicher), um eine bessere Leistung zu erzielen. Die Schnittstelle ist die gleiche.
Asaph
2
Dies scheint von snippets.dzone.com/posts/show/91 zu stammen . Die Kommentare deuten auf eine stark verbesserte Version hin: public static String join (Iterable <? Erweitert Objekt> pColl, String-Trennzeichen) {Iterator <? erweitert Object> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) return ""; StringBuilder oBuilder = neuer StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (Trennzeichen) .append (oIter.next ()); return oBuilder.toString (); }
Quantum7
6

Wenn Sie hier gelandet sind und nach einer schnellen Konvertierung von Array zu String suchen, versuchen Sie es mit Arrays.toString () .

Erstellt eine String-Darstellung des Object[]übergebenen. Das Ergebnis ist von Klammern ( "[]") umgeben. Jedes Element wird über das in einen String konvertiert String.valueOf(Object)und durch getrennt ", ". Wenn das Array ist null, "null"wird zurückgegeben.

quietmint
quelle
VIELEN DANK! Die Zeichenfolgen sind durch "," getrennt und das Ganze hat "[]", was für mich in Ordnung ist.
John Henckel
5

Nur für die "Ich habe die kürzeste" Herausforderung, hier sind Minen;)

Iterativ:

public static String join(String s, Object... a) {
    StringBuilder o = new StringBuilder();
    for (Iterator<Object> i = Arrays.asList(a).iterator(); i.hasNext();)
        o.append(i.next()).append(i.hasNext() ? s : "");
    return o.toString();
}

Rekursiv:

public static String join(String s, Object... a) {
    return a.length == 0 ? "" : a[0] + (a.length == 1 ? "" : s + join(s, Arrays.copyOfRange(a, 1, a.length)));
}
sp00m
quelle
2
Die rekursive Version ist elegant. Ich werde das auf jeden Fall nutzen.
Pete
Die rekursive Version ist zwar elegant, für große Arrays jedoch ineffizient (" copyOfRange()").
Oger Psalm33
4

Nichts eingebaut, von dem ich weiß.

Apache Commons Lang hat eine Klasse namens, StringUtilsdie viele Verknüpfungsfunktionen enthält.

JonMR
quelle
4

So mache ich es.

private String join(String[] input, String delimiter)
{
    StringBuilder sb = new StringBuilder();
    for(String value : input)
    {
        sb.append(value);
        sb.append(delimiter);
    }
    int length = sb.length();
    if(length > 0)
    {
        // Remove the extra delimiter
        sb.setLength(length - delimiter.length());
    }
    return sb.toString();
}
Richard Corfield
quelle
2

Eine ähnliche Alternative

/**
 * @param delimiter 
 * @param inStr
 * @return String
 */
public static String join(String delimiter, String... inStr)
{
    StringBuilder sb = new StringBuilder();
    if (inStr.length > 0)
    {
        sb.append(inStr[0]);
        for (int i = 1; i < inStr.length; i++)
        {
            sb.append(delimiter);                   
            sb.append(inStr[i]);
        }
    }
    return sb.toString();
}
William Simpson
quelle
2

Mein Spin.

public static String join(Object[] objects, String delimiter) {
  if (objects.length == 0) {
    return "";
  }
  int capacityGuess = (objects.length * objects[0].toString().length())
      + ((objects.length - 1) * delimiter.length());
  StringBuilder ret = new StringBuilder(capacityGuess);
  ret.append(objects[0]);
  for (int i = 1; i < objects.length; i++) {
    ret.append(delimiter);
    ret.append(objects[i]);
  }
  return ret.toString();
}

public static String join(Object... objects) {
  return join(objects, "");
}
Jackson
quelle
1

Gefällt dir mein 3-Zeilen-Weg nur mit den Methoden der String-Klasse?

static String join(String glue, String[] array) {
    String line = "";
    for (String s : array) line += s + glue;
    return (array.length == 0) ? line : line.substring(0, line.length() - glue.length());
}
Ryoichiro Oka
quelle
1
Es soll nicht effizient sein. Verwenden StringBuilderSie, wenn Sie Effizienz benötigen: P
Ryoichiro Oka
0

Um "str1, str2" von "str1", "str2", "" zu erhalten:

Stream.of("str1", "str2", "").filter(str -> !str.isEmpty()).collect(Collectors.joining(", ")); 

Sie können auch eine zusätzliche Nullprüfung hinzufügen

ema
quelle
0

Falls Sie eine funktionale Java-Bibliothek verwenden und aus irgendeinem Grund keine Streams aus Java 8 verwenden können (was bei Verwendung des Android + Retrolambda-Plugins der Fall sein kann), finden Sie hier eine funktionale Lösung für Sie:

String joinWithSeparator(List<String> items, String separator) {
    return items
            .bind(id -> list(separator, id))
            .drop(1)
            .foldLeft(
                    (result, item) -> result + item,
                    ""
            );
}

Beachten Sie, dass dies nicht der effizienteste Ansatz ist, aber für kleine Listen gut funktioniert.

Dmitry Zaytsev
quelle
-1

Ich mache es so mit einem StringBuilder:

public static String join(String[] source, String delimiter) {
    if ((null == source) || (source.length < 1)) {
        return "";
    }

    StringBuilder stringbuilder = new StringBuilder();
    for (String s : source) {
        stringbuilder.append(s + delimiter);
    }
    return stringbuilder.toString();
} // join((String[], String)
spanky762
quelle
1
s + delimiter(Zeichenfolgenverkettung mit dem Plus-Operator) macht den gesamten Zweck der Verwendung von a zunichte StringBuilder.
quietmint
Außerdem würde dieser Ansatz bedeuten, dass ein Array wie: {"foo", "bar"} mit Trennzeichen ":" in "foo: bar:" umgewandelt wird
pioto
-2

Es gibt eine einfache Kurzschrifttechnik, die ich meistens benutze.

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);
Gaurav Adurkar
quelle
Dies funktioniert nur mit Trennzeichen der Länge 1 und erfordert 'magische Zahlen' (obwohl ziemlich lokal), wenn Sie ein Trennzeichen einer anderen Länge wünschen.
Maiwald
Sie können beim Anhängen mehrere Zeichen hinzufügen
Gaurav Adurkar
als einfach zu tun: op = op.substring (0, op.length () - ",". length ()); Was ist die große Sache?
Dennis
-3

java.util.Arrays hat eine 'asList'-Methode. Zusammen mit der API java.util.List / ArrayList erhalten Sie alles, was Sie brauchen:;

private static String[] join(String[] array1, String[] array2) {

    List<String> list = new ArrayList<String>(Arrays.asList(array1));
    list.addAll(Arrays.asList(array2));
    return list.toArray(new String[0]);
}
Adriaan Koster
quelle
7
Die Frage ist, wie ein String-Array mit einem Trennzeichen verbunden wird und nicht, wie zwei String-Arrays miteinander verbunden werden.
Toolbear