Java-эквивалент PHP implode (',', array filter (array ())


Я часто использую этот кусок кода в 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"

какая лучшая реализация Java (меньше кода) в Java без необходимости добавлять внешние библиотеки (разработка для Android) ?

9 61

9 ответов:

обновленная версия с использованием Java 8 (Оригинал в конце поста)

Если вам не нужно фильтровать любые элементы, вы можете использовать


начиная с Java 8, мы можем использовать StringJoiner (вместо первоначально использовались StringBulder) и упростить наш код.
Также, чтобы избежать перекомпиляции " *" regex в каждом вызове matches(" *") мы можем создать отдельный шаблон, который будет содержать его скомпилированную версию в некотором поле и использовать его при необходимости.

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 элементов 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

почему так серьезно? Попробуй StringUtils.join(new String[] {"Hello", "World", "!"}, ", ") !

вам нужно будет добавить свои строки в 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));

вот конкретный ответ Android, который может быть полезен некоторым

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

//Result => Red,Green,Blue

обязательно импортируйте класс TextUtils

import android.text.TextUtils;

использование потоков (для java 8 и более поздних версий) было бы альтернативным возможным решением для этого. Вы должны импортировать

java.util.stream.Collectors;

чтобы использовать процесс соединения

Вы можете использовать:

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

для достижения желаемого результата.

простой взрыв

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 implode.
Вот что вы хотите:

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

вот моя реализация implode:

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

используйте эту простую функцию :

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"