Java: funzione per array come join () di PHP?


Risposte:


307

A partire da Java8 è possibile utilizzare String.join().

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

genera:

Hello, World, !

Altrimenti, Apache Commons Lang ha una StringUtilsclasse che ha una joinfunzione che unirà le matrici per creare un String.

Per esempio:

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

Genera quanto segue String:

Hello, World, !

7
A beneficio delle persone che cercano questa risposta, probabilmente si dovrebbe notare che questo è anche l'equivalente di un join Perl.
k-den,

3
dice che non è definito per me
Ninjaxor

@Ninjaxor 1. Il vaso commons-lang * deve trovarsi nel percorso di classe 2. import org.apache.commons.lang3.StringUtils;
Peter - Ripristina Monica il

9
Ti consiglio di modificare questa risposta per aggiungere un riferimento al nuovo String.join()metodo introdotto in Java 8. In questo modo, l'enorme numero di persone che leggono questa risposta accettata trarrà beneficio da quella conoscenza. Attualmente, la risposta più votata che menziona questo fatto è piuttosto persa sotto ...
Duncan Jones,

1
Vale la pena ricordare che String.join()funzionerebbe solo per List<CharSequence>o CharSequence[]elementi.
Enigo,

71

Se stavi cercando cosa usare in Android, è:

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

per esempio:

String joined = TextUtils.join(";", MyStringArray);

2
Questa è chiaramente la risposta migliore per tutte le versioni di Android, poiché Java 8 uscirà su Android solo un po '. Questa soluzione utilizza le librerie Android integrate, piuttosto che queste sciocche "include una vasta libreria per eseguire un'azione".
LukeStoneHm,

È settembre 2017, Java 8 per Android è ancora lontano. Grazie per questa risposta!
Aenadon,


53

Si potrebbe facilmente scrivere una tale funzione in circa dieci righe di codice:

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
Buone pratiche secondo te ... non esiste uno standard universale per queste cose.
phoebus il

24
Ma se includessi parentesi graffe, ciò avrebbe aggiunto altre due righe di codice e non avrei potuto affermare di averlo fatto in 11 righe!
Jay,

8
il problema è quando dopo un po ', o qualcun altro, in fretta, aggiungi un'altra riga a quella se / per senza aggiungere parentesi graffe; oppure elimina return null dopo if (k == 0), che in alcuni casi verrà compilato ma non sarà corretto. Quindi è meglio sacrificare una riga aggiuntiva per quella parentesi graffa di chiusura (l'apertura può rimanere nella stessa if / for line).
milano,

16
Penso che sia fantastico che mentre la maggior parte delle lingue racchiuda tale funzionalità nel proprio core, la comunità Java incoraggi tutti a reinventare la ruota.
John Strickler,

33
11 linee? Bah! Posso farlo in 1! Rimuovi semplicemente tutti i caratteri di nuova riga nel file di origine.
Thomas Eding,

25

Una piccola mod invece di usare la sottostringa ():

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

Votato perché non è necessario aggiungere alcuna libreria.
givanse,

10
Riga 7: è meglio se usato .append()due volte per ciascuno Stringinvece di concatenarli e quindi aggiungerli al builder.
Talha Ahmed Khan,

18

Come con molte domande di recente, Java 8 in soccorso:


Java 8 ha aggiunto un nuovo metodo statico al java.lang.Stringquale fa esattamente quello che vuoi:

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

Usandolo:

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

Risultati in:

"Hello, World, !"

14

Anche la libreria di Google guava ha questo tipo di funzionalità . Puoi vedere l'esempio String [] anche dall'API.

Come già descritto nell'API, fai attenzione all'immutabilità dei metodi di costruzione.

Può accettare una serie di oggetti, quindi funzionerà nel tuo caso. Nella mia precedente esperienza, ho provato a unirmi a uno Stack che è iterabile e funziona benissimo.

Campione da me:

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

stampa: |i am a coder|


9

Dato:

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

Quindi come alternativa alla risposta di coobird, dove la colla è ",":

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

O concatenare con una stringa diversa, come "& amp;".

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

Tuttavia ... questo funziona SOLO se sai che i valori nella matrice o nell'elenco NON contengono la stringa di caratteri ",".


Arrays.asList(a).toString()ha lavorato per quello che volevo fare
Solomon Ucko

9

Se stai usando Spring Framework allora hai la classe StringUtils :

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

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

8

Non nel nocciolo, no. Una ricerca di "colla per stringhe di join java array" ti fornirà alcuni frammenti di codice su come raggiungere questo obiettivo.

per esempio

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
Utilizzare StringBuilder (non thread-safe) al posto di StringBuffer (thread-safe) per prestazioni migliori. L'interfaccia è la stessa.
Asaf

2
Questo sembra provenire da snippets.dzone.com/posts/show/91 . I commenti suggeriscono una versione molto migliorata: join statico pubblico String (Iterable <? Extends Object> pColl, Separatore di stringhe) {Iteratore <? estende Object> oIter; if (pColl == null || (! (oIter = pColl.iterator ()) .hasNext ())) restituisce ""; StringBuilder oBuilder = new StringBuilder (String.valueOf (oIter.next ())); while (oIter.hasNext ()) oBuilder.append (separator) .append (oIter.next ()); return oBuilder.toString (); }
Quantum7

6

Se sei arrivato qui alla ricerca di una rapida conversione da array a stringa, prova Arrays.toString () .

Crea una rappresentazione String del Object[]passato. Il risultato è racchiuso tra parentesi ( "[]"), ogni elemento viene convertito in una stringa tramite il String.valueOf(Object)e separato da ", ". Se l'array è null, "null"viene restituito.


GRAZIE MILLE! Le stringhe sono separate da "," e il tutto ha "[]" attorno, il che mi sta bene.
John Henckel,

5

Solo per la sfida "Ho la più breve" , ecco le mine;)

Iterativo:

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

Ricorsivo:

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
La versione ricorsiva è elegante. Sicuramente lo userò.
Pete,

La versione ricorsiva può essere elegante, ma inefficiente per array di grandi dimensioni (" copyOfRange()").
Ogre Salmo33


4

Questo è come lo faccio.

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

Un'alternativa simile

/**
 * @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

Il mio giro.

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

Ti piace il mio modo a 3 righe usando solo i metodi della classe String?

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
Non è pensato per essere efficiente. Usa StringBuilderse hai bisogno di efficienza: P
Ryoichiro Oka

0

Per ottenere "str1, str2" da "str1", "str2", "":

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

Inoltre è possibile aggiungere un ulteriore controllo null


0

Nel caso in cui tu stia utilizzando la libreria Java funzionale e per qualche motivo non riesci a utilizzare Streams da Java 8 (che potrebbe essere il caso quando si utilizza il plug-in Android + Retrolambda), ecco una soluzione funzionale per te:

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

Si noti che non è l'approccio più efficiente, ma funziona bene per piccoli elenchi.


-1

Lo faccio in questo modo usando un 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(concatenazione di stringhe con l'operatore plus) vanifica l'intero scopo dell'uso di a StringBuilder.
quietmint

Inoltre, questo approccio significherebbe che un array come: {"pippo", "bar"} con delimitatore ":" verrebbe trasformato in "pippo: bar:"
pioto,

-2

Esiste una semplice tecnica abbreviata che uso la maggior parte delle volte.

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);

Funziona solo con delimitatori di lunghezza 1 e richiede "numeri magici" (anche se abbastanza locali) se si desidera un delimitatore di lunghezza diversa.
maiwald,

Puoi aggiungere più personaggi durante l'aggiunta
Gaurav Adurkar

che semplicemente: op = op.substring (0, op.length () - ",". length ()); qual è il grosso problema?
Dennis,

-3

java.util.Arrays ha un metodo 'asList'. Insieme all'API java.util.List / ArrayList ti offre tutto ciò di cui hai bisogno :;

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
La domanda è come unire un array di stringhe con un delimitatore, non come unire insieme due array di stringhe.
toolbear,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.