Каков наилучший способ создать строку элементов с разделителями в Java? - PullRequest
275 голосов
/ 15 сентября 2008

Работая в приложении Java, я недавно должен был собрать список значений, разделенных запятыми, для передачи в другой веб-сервис, не зная, сколько элементов будет заранее. Лучшее, что я мог придумать, это было примерно так:

public String appendWithDelimiter( String original, String addition, String delimiter ) {
    if ( original.equals( "" ) ) {
        return addition;
    } else {
        return original + delimiter + addition;
    }
}

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

Я понимаю, что это не особенно эффективно, поскольку повсюду создаются строки, но я собирался сделать это для большей ясности, чем для оптимизации.

В Ruby я могу сделать что-то вроде этого, что выглядит намного элегантнее:

parameterArray = [];
parameterArray << "elementName" if condition;
parameterArray << "anotherElementName" if anotherCondition;
parameterString = parameterArray.join(",");

Но поскольку в Java нет команды соединения, я не смог найти ничего эквивалентного.

Итак, как лучше всего это сделать в Java?

Ответы [ 35 ]

0 голосов
/ 15 сентября 2008

Вместо использования конкатенации строк следует использовать StringBuilder, если ваш код не является многопоточным, и StringBuffer, если он есть.

0 голосов
/ 15 сентября 2008

Вы делаете это немного сложнее, чем должно быть. Давайте начнем с конца вашего примера:

String parameterString = "";
if ( condition ) parameterString = appendWithDelimiter( parameterString, "elementName", "," );
if ( anotherCondition ) parameterString = appendWithDelimiter( parameterString, "anotherElementName", "," );

С небольшим изменением использования StringBuilder вместо String это становится:

StringBuilder parameterString = new StringBuilder();
if (condition) parameterString.append("elementName").append(",");
if (anotherCondition) parameterString.append("anotherElementName").append(",");
...

Когда вы закончите (я предполагаю, что вы должны проверить и несколько других условий), просто убедитесь, что вы удаляете запятую с помощью такой команды:

if (parameterString.length() > 0) 
    parameterString.deleteCharAt(parameterString.length() - 1);

И наконец, получите желаемую строку с

parameterString.toString();

Вы также можете заменить "," во втором вызове, чтобы добавить общую строку-разделитель, которая может быть установлена ​​на что угодно. Если у вас есть список вещей, которые, как вы знаете, нужно добавить (безоговорочно), вы можете поместить этот код в метод, который принимает список строк.

0 голосов
/ 16 сентября 2008

Итак, пара вещей, которые вы могли бы сделать, чтобы создать ощущение, будто вы ищете:

1) Расширьте класс List - и добавьте в него метод join. Метод join будет просто выполнять конкатенацию и добавление разделителя (который может быть параметром метода join)

2) Похоже, что в Java 7 будут добавлены методы расширения в java, что позволит вам просто прикрепить определенный метод к классу: чтобы вы могли написать этот метод соединения и добавить его в качестве метода расширения в List или даже в коллекцию.

Решение 1, вероятно, является единственным реалистичным, хотя, поскольку Java 7 еще не выпущена :) Но оно должно работать просто отлично.

Чтобы использовать оба из них, вы просто добавляете все свои элементы в Список или Коллекцию как обычно, а затем вызываете новый пользовательский метод, чтобы «присоединиться» к ним.

0 голосов
/ 26 июля 2010

Небольшое улучшение [скорость] версии от izb:

public static String join(String[] strings, char del)
{
    StringBuilder sb = new StringBuilder();
    int len = strings.length;

    if(len > 1) 
    {
       len -= 1;
    }else
    {
       return strings[0];
    }

    for (int i = 0; i < len; i++)
    {
       sb.append(strings[i]).append(del);
    }

    sb.append(strings[i]);

    return sb.toString();
}
0 голосов
/ 01 февраля 2010

, используя Dollar , просто набрав:

String joined = $(aCollection).join(",");

Примечание: работает также для массивов и других типов данных

Осуществление

Внутренне он использует очень аккуратный трюк:

@Override
public String join(String separator) {
    Separator sep = new Separator(separator);
    StringBuilder sb = new StringBuilder();

    for (T item : iterable) {
        sb.append(sep).append(item);
    }

    return sb.toString();
}

класс Separator возвращает пустую строку только при первом ее вызове, затем возвращает разделитель:

class Separator {

    private final String separator;
    private boolean wasCalled;

    public Separator(String separator) {
        this.separator = separator;
        this.wasCalled = false;
    }

    @Override
    public String toString() {
        if (!wasCalled) {
            wasCalled = true;
            return "";
        } else {
            return separator;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...