Une méthode pour inverser l'effet de java Chaîne.split ()?
je suis à la recherche d'une méthode pour combiner un tableau de chaînes dans un délimité Chaîne. Un face à split(). J'ai vu cela dans d'autres langues.
voulait demander au forum avant que j'essaye d'écrire le mien( puisque le JDK a tout...)
Merci,
16 réponses
il n'y a pas de méthode dans le JDK pour ça que je sache. Apache Commons Lang a diverses méthodes surchargées join()
dans la classe StringUtils
qui font ce que vous voulez.
il y a une demande de caractéristique ouverte depuis au moins 2009. Le long et le court de celui-ci est qu'il fera partie de la fonctionnalité de java de JDK 8.util.Classe StringJoiner. http://download.java.net/lambda/b81/docs/api/java/util/StringJoiner.html
Voici la question Oracle si vous êtes intéressé. http://bugs.sun.com/view_bug.do?bug_id=5015163
mise à Jour
ici est un exemple du nouveau noeud de chaîne JDK 8 sur un tableau de chaîne
String[] a = new String[]{"first","second","third"};
StringJoiner sj = new StringJoiner(",");
for(String s:a) sj.add(s);
System.out.println(sj); //first,second,third
une méthode utilitaire dans String rend cela encore plus simple:
String s = String.join(",", stringArray);
vous pouvez faire sortir cette fonctionnalité du paquet utilitaire Arrays
.
import java.util.Arrays;
...
String delim = ":",
csv_record = "Field0:Field1:Field2",
fields[] = csv_record.split(delim);
String rebuilt_record = Arrays.toString(fields).replace(", ", delim).replaceAll("[\[\]]", "");
j'ai l'exemple suivant ici
/*
7) Join Strings using separator >>>AB$#$CD$#$EF
*/
import org.apache.commons.lang.StringUtils;
public class StringUtilsTrial {
public static void main(String[] args) {
// Join all Strings in the Array into a Single String, separated by $#$
System.out.println("7) Join Strings using separator >>>"
+ StringUtils.join(new String[] { "AB", "CD", "EF" }, "$#$"));
}
}
Google fournit également une classe de menuisier dans leur bibliothèque de Collections Google:
il y a plusieurs exemples sur Dzone si vous voulez rouler votre propre qui fonctionne avec une Collection. Par exemple:
public static String join(AbstractCollection<String> s, String delimiter) {
if (s == null || s.isEmpty()) return "";
Iterator<String> iter = s.iterator();
StringBuilder builder = new StringBuilder(iter.next());
while( iter.hasNext() )
{
builder.append(delimiter).append(iter.next());
}
return builder.toString();
}
si vous avez un int [], Arrays.toString()
est la façon la plus facile.
Basé sur toutes les réponses précédentes:
public static String join(Iterable<? extends Object> elements, CharSequence separator)
{
StringBuilder builder = new StringBuilder();
if (elements != null)
{
Iterator<? extends Object> iter = elements.iterator();
if(iter.hasNext())
{
builder.append( String.valueOf( iter.next() ) );
while(iter.hasNext())
{
builder
.append( separator )
.append( String.valueOf( iter.next() ) );
}
}
}
return builder.toString();
}
pour Android: en android.texte.TextUtils il y a des méthodes:
public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)
renvoie une chaîne contenant les jetons rejoints par des délimiteurs.
jetons -- un tableau d'objets à assembler. Les cordes seront formées à partir des objets en appelant l'objet.toString ().
celui-là est pas mal aussi :
public static String join(String delimitor,String ... subkeys) {
String result = null;
if(null!=subkeys && subkeys.length>0) {
StringBuffer joinBuffer = new StringBuffer(subkeys[0]);
for(int idx=1;idx<subkeys.length;idx++) {
joinBuffer.append(delimitor).append(subkeys[idx]);
}
result = joinBuffer.toString();
}
return result;
}
j'ai écrit celui-ci:
public static String join(Collection<String> col, String delim) {
StringBuilder sb = new StringBuilder();
Iterator<String> iter = col.iterator();
if (iter.hasNext())
sb.append(iter.next());
while (iter.hasNext()) {
sb.append(delim);
sb.append(iter.next());
}
return sb.toString();
}
Collection
n'est pas pris en charge par JSP, donc pour le TLD, j'ai écrit:
public static String join(List<?> list, String delim) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
sb.append(delim);
sb.append(list.get(i).toString());
}
return sb.toString();
}
et mis à .tld
fichier:
<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
<function>
<name>join</name>
<function-class>com.core.util.ReportUtil</function-class>
<function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
</function>
</taglib>
et l'utiliser dans les fichiers JSP comme:
<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}
par souci d'exhaustivité, je voudrais ajouter que vous ne pouvez pas inverser String#split en général, car il accepte une expression régulière.
"hello__world".split("_+");
Rendements ["hello", "world"]
.
"hello_world".split("_+");
Rendements ["hello", "world"]
.
ces résultats donnent des résultats identiques à partir d'un point de départ différent. le fractionnement n'est pas une opération à un contre un et est donc non réversible.
tout cela étant cela dit, si vous supposez que votre paramètre est une chaîne fixe, pas un regex, alors vous pouvez certainement le faire en utilisant l'une des nombreuses réponses postées.
code ci-dessous donne une idée de base. Ce n'est pas la meilleure solution.
public static String splitJoin(String sourceStr, String delim,boolean trim,boolean ignoreEmpty){
return join(Arrays.asList(sourceStr.split(delim)), delim, ignoreEmpty);
}
public static String join(List<?> list, String delim, boolean ignoreEmpty) {
int len = list.size();
if (len == 0)
return "";
StringBuilder sb = new StringBuilder(list.get(0).toString());
for (int i = 1; i < len; i++) {
if (ignoreEmpty && !StringUtils.isBlank(list.get(i).toString())) {
sb.append(delim);
sb.append(list.get(i).toString().trim());
}
}
return sb.toString();
}
depuis JDK8 j'aime beaucoup les ruisseaux et Lambdas, donc je suggérerais:
public static String join( String delimiter, String[] array )
{
return Arrays.asList( array ).stream().collect( Collectors.joining( delimiter ) );
}
j'aime mieux cela:
public String join(Collection<String> strCollection, String delimiter) {
String joined = "";
int noOfItems = 0;
for (String item : strCollection) {
joined += item;
if (++noOfItems < strCollection.size())
joined += delimiter;
}
return joined;
}
C'est la meilleure solution que j'ai trouvée jusqu'à présent. (Ne vous souciez pas de l'utilisation d'objets String bruts au lieu de StringBuilder. Les compilateurs Java modernes utilisent de toute façon StringBuilder, mais ce code est plus lisible).
si vous utilisez jdk8, voyez la réponse de @Nathaniel Johnson 151940920" comme c'est mieux.
je pense que beaucoup de la réponse ici sont complexes ou pas facile à lire. Avec la prédiction de branche si efficace pourquoi vous n'utilisez tout simplement pas une instruction if?
public static String join(List<String> fooList){
if (fooList.isEmpty()) return "";
StringBuilder sb = null;
for (String element : fooList) {
if (sb == null) {
sb = new StringBuilder();
} else {
sb.append(", ");
}
sb.append(element);
}
return sb.toString();
}
quelque chose qui devrait être mentionné est Qu'Apache utilise une boucle simple avec une instruction if à l'intérieur comme ceci (il utilise un tableau comme son index pour savoir le premier élément), et openjdk 8 fait la même chose mais dans les méthodes séparées les appels au lieu d'une simple boucle.