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


259

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


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, !

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);

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();
}

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();
}

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, !"

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|


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.


Arrays.asList(a).toString()arbeitete für das, was ich tun wollte
Solomon Ucko


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();
}

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.


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)));
}

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

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();
}

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();
}

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, "");
}

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());
}

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


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.


-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)

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);

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]);
}

7
Die Frage ist, wie ein String-Array mit einem Trennzeichen verbunden wird und nicht, wie zwei String-Arrays miteinander verbunden werden.
Toolbear
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.