81

我经常在 PHP 中使用这段代码

$ordine['address'] = implode(', ', array_filter(array($cliente['cap'], $cliente['citta'], $cliente['provincia'])));

它清除空字符串并用“,”连接它们。如果只剩下一个,它不会添加额外的不需要的逗号。它不会在末尾添加逗号。如果没有剩余,则返回空字符串。

因此我可以得到以下结果之一

""
"Street abc 14"
"Street abc 14, 00168"
"Street abc 14, 00168, Rome"

无需添加外部库(为 Android 设计)的 Java 中最好的 Java 实现(更少代码)是什么?

4

9 回答 9

95

使用 Java 8 的更新版本(原始在帖子末尾)

如果您不需要过滤任何可以使用的元素


从 Java 8 开始,我们可以使用StringJoiner(而不是最初使用的StringBulder)并简化我们的代码。
此外,为了避免" *"在每次调用中重新编译正则表达式,matches(" *")我们可以创建单独的 Pattern,它将在某些字段中保存其编译版本并在需要时使用它。

private static final Pattern SPACES_OR_EMPTY = Pattern.compile(" *");
public static String implode(String separator, String... data) {
    StringJoiner sb = new StringJoiner(separator);
    for (String token : data) {
        if (!SPACES_OR_EMPTY.matcher(token).matches()) {
            sb.add(token);
        }
    }
    return sb.toString();
}   

使用流,我们的代码可以看起来像。

private static final Predicate<String> IS_NOT_SPACES_ONLY = 
        Pattern.compile("^\\s*$").asPredicate().negate();

public static String implode(String delimiter, String... data) {
    return Arrays.stream(data)
            .filter(IS_NOT_SPACES_ONLY)
            .collect(Collectors.joining(delimiter));
}

如果我们使用流,我们可以filter元素 which Predicate。在这种情况下,我们希望谓词接受不仅是空格的字符串 - 换句话说,字符串必须包含非空白字符。

我们可以从 Pattern 中创建这样的 Predicate。以这种方式创建的谓词将接受任何包含正则表达式可以匹配的子字符串的字符串(因此,如果正则表达式将查找"\\S"谓词,则将接受像"foo ", " foo bar ",之类的字符串"whatever",但不接受" "也不接受" ")。

所以我们可以使用

Pattern.compile("\\S").asPredicate();

或者可能更具描述性,否定只有空格或空的字符串

Pattern.compile("^\\s*$").asPredicate().negate();

接下来,当过滤器将删除所有空的或仅包含空格的字符串时,我们可以collect其余元素。感谢Collectors.joining我们可以决定使用哪个分隔符。


原始答案(Java 8 之前)

public static String implode(String separator, String... data) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < data.length - 1; i++) {
    //data.length - 1 => to not add separator at the end
        if (!data[i].matches(" *")) {//empty string are ""; " "; "  "; and so on
            sb.append(data[i]);
            sb.append(separator);
        }
    }
    sb.append(data[data.length - 1].trim());
    return sb.toString();
}

你可以像这样使用它

System.out.println(implode(", ", "ab", " ", "abs"));

或者

System.out.println(implode(", ", new String[] { "ab", " ", "abs" }));

输出ab, abs

于 2012-06-28T16:11:24.480 回答
80

为什么如此严肃?试试看StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

于 2013-01-29T14:10:55.840 回答
20

这是一个特定于 Android 的答案,可能对某些人有帮助:

String combined = TextUtils.join(",", new String[]{"Red", "Green", "Blue"});

// Result => Red,Green,Blue

请务必导入 TextUtils 类:

import android.text.TextUtils;
于 2016-01-13T00:59:36.040 回答
17

您必须将字符串添加到 ArrayList,删除空字符串,并相应地对其进行格式化:

public static String createAddressString( String street, String zip_code, String country) {
    List<String> list = new ArrayList<String>();
    list.add( street);
    list.add( zip_code);
    list.add( country);

    // Remove all empty values
    list.removeAll(Arrays.asList("", null));

    // If this list is empty, it only contained blank values
    if( list.isEmpty()) {
        return "";
    }

    // Format the ArrayList as a string, similar to implode
    StringBuilder builder = new StringBuilder();
    builder.append( list.remove(0));

    for( String s : list) {
        builder.append( ", ");
        builder.append( s);
    }

    return builder.toString();
}

此外,如果您有String[]一个字符串数组,您可以轻松地将它们添加到 ArrayList:

String[] s;
List<String> list = new ArrayList<String>( Arrays.asList( s));
于 2012-06-28T15:50:30.247 回答
3

使用 Streams(用于Java 8及更高版本)将是另一种可能的解决方案。

您需要导入

java.util.stream.Collectors;

使用加入过程

您可以使用:

Arrays.asList("foo","bar").stream().collect(Collectors.joining(","));

以达到预期的结果。

于 2017-02-18T12:17:27.490 回答
2

一个简单的内爆

public static String implode(String glue, String[] strArray)
{
    String ret = "";
    for(int i=0;i<strArray.length;i++)
    {
        ret += (i == strArray.length - 1) ? strArray[i] : strArray[i] + glue;
    }
    return ret;
}

你可以为它创建重载..

上面它相当于 php 内爆。
这是你想要的:

import java.lang.*
public static String customImplode(String glue, String[] strArray)
{
    String ret = "";
    for(int i=0;i<strArray.length;i++)
    {
        if (strArray[i].trim() != "")
            ret += (i == strArray.length - 1) ? strArray[i] : strArray[i] + glue;
    }
    return ret;
}
于 2012-06-28T15:47:25.380 回答
1

这是我的内爆实现:

/**
 * Implodes the specified items, gluing them using the specified glue replacing nulls with the specified
 * null placeholder.
 * @param glue              The text to use between the specified items.
 * @param nullPlaceholder   The placeholder to use for items that are <code>null</code> value.
 * @param items             The items to implode.
 * @return  A <code>String</code> containing the items in their order, separated by the specified glue.
 */
public static final String implode(String glue, String nullPlaceholder, String ... items) {
    StringBuilder sb = new StringBuilder();
    for (String item : items) {
        if (item != null) {
            sb.append(item);
        } else {
            sb.append(nullPlaceholder);
        }
        sb.append(glue);
    }
    return sb.delete(sb.length() - glue.length(), sb.length()).toString();
}
于 2013-11-02T12:49:04.923 回答
1
public static String implode(List<String> items, String separator) {

        if (items == null || items.isEmpty()) {
            return null;
        }
        String delimiter = "";
        StringBuilder builder = new StringBuilder();
        for (String item : items) {
            builder.append(delimiter).append(item);
            delimiter = separator;
        }
        return builder.toString();
    }
于 2016-03-28T01:41:56.960 回答
0

使用这个简单的功能:

private String my_implode(String spacer, String[] in_array){

    String res = "";

    for (int i = 0 ; i < in_array.length ; i++) {

        if (!res.equals("")) {
            res += spacer;
        }
        res += in_array[i];
    }

    return res;
}

利用:

data_arr = {"d1", "d2", "d3"};
your_imploded_text = my_implode(",", data_arr);
// Output: your_imploded_text = "d1,d2,d3"
于 2015-10-26T08:56:39.487 回答