Как реализовать сгиб списка в Java

Общее руководство по дизайну: если первая реакция разумного человека на < набор вещей > Вероятно, это может быть "Это слишком много вещей!", тогда это слишком много вещей.

23
задан Peter Kofler 7 September 2010 в 18:12
поделиться

7 ответов

К сожалению, Java не является функциональным языком программирования и у нее нет хорошего способа делать то, что вы хотите.

Я считаю, что в Apache Commons lib есть функция , называемая join , который будет делать то, что вы хотите.

Он должен быть достаточно хорошим, чтобы скрыть цикл в методе.

public static String combine(List<String> list, String separator){
    StringBuilder ret = new StringBuilder();
    for(int i = 0; i < list.size(); i++){
        ret.append(list.get(i));
        if(i != list.size() - 1)
            ret.append(separator);
    }
    return ret.toString();
}

Я полагаю, вы могли бы сделать это рекурсивно:

public static String combine(List<String> list, String separator){
    return recursiveCombine("", list, 0, separator);
}

public static String recursiveCombine(String firstPart, List<String> list, int posInList, String separator){
    if (posInList == list.size() - 1) return firstPart + list.get(posInList);

    return recursiveCombine(firstPart + list.get(posInList) + separator, list, posInList + 1, seperator);
}
1
ответ дан 29 November 2019 в 01:38
поделиться

К сожалению, в Java вы не можете избежать этого цикла, однако существует несколько библиотек. Например, вы можете попробовать несколько библиотек:

2
ответ дан 29 November 2019 в 01:38
поделиться

Учитывая

public static <T,Y> Y fold(Collection<? extends T> list, Injector<T,Y> filter){
  for (T item : list){
    filter.accept(item);
  }
  return filter.getResult();
}

public interface Injector<T,Y>{
  public void accept(T item);
  public Y getResult();
}

Тогда использование выглядит как

fold(myArray, new Injector<String,String>(){
  private StringBuilder sb = new StringBuilder();
  public void Accept(String item){ sb.append(item); }
  public String getResult() { return sb.toString(); }
}
);
10
ответ дан 29 November 2019 в 01:38
поделиться

Что вы ищите строковую функцию "соединения", которой, к сожалению, нет в Java. Вам придется использовать собственную функцию соединения, которая не должна быть слишком сложной.

Изменить: org.apache.commons.lang.StringUtils , похоже, имеет много полезных строковых функций (включая соединение).

6
ответ дан 29 November 2019 в 01:38
поделиться

Чтобы ответить на ваш исходный вопрос:

public static <A, B> A fold(F<A, F<B, A>> f, A z, Iterable<B> xs)
{ A p = z;
  for (B x : xs)
    p = f.f(p).f(x);
  return p; }

Где F выглядит так:

public interface F<A, B> { public B f(A a); }

Как было предложено dfa, Функциональная Java имеет это и многое другое.

Пример 1:

import fj.F;
import static fj.data.List.list;
import static fj.pre.Monoid.stringMonoid;
import static fj.Function.flip;
import static fj.Function.compose;

F<String, F<String, String>> sum = stringMonoid.sum();
String abc = list("a", "b", "c").foldLeft1(compose(sum, flip(sum).f(",")));

Пример 2:

import static fj.data.List.list;
import static fj.pre.Monoid.stringMonoid;
...
String abc = stringMonoid.join(list("a", "b", "c"), ",");

Пример 3:

import static fj.data.Stream.fromString;
import static fj.data.Stream.asString;
...
String abc = asString(fromString("abc").intersperse(','));
13
ответ дан 29 November 2019 в 01:38
поделиться

Инструменты → Параметры импорта и экспорта → Импортировать параметры выбранной среды .. .

Появится диалоговое окно, предлагающее вам сохранить текущие настройки или нет. Если вы внесли обширные изменения и, возможно, захотите вернуться к ним позже, вам следует выбрать их сохранение.

Затем нажмите «Далее». Вам будет предложено импортировать набор настроек среды. Вверху будут параметры настройки среды по умолчанию, настроенные для каждого языка. В вашем случае вы должны выбрать C #.

Если вы хотите повторно импортировать сохраненные настройки, вы должны сделать это таким же образом - просто перейдите к сохраненному файлу настроек на последнем шаге мастера.

предлагая вам сохранить текущие настройки или нет. Если вы внесли обширные изменения и, возможно, захотите вернуться к ним позже, вам следует выбрать их сохранение.

Затем нажмите «Далее». Вам будет предложено импортировать набор настроек среды. Вверху будут параметры настройки среды по умолчанию, настроенные для каждого языка. В вашем случае вы должны выбрать C #.

Если вы хотите повторно импортировать сохраненные настройки, вы должны сделать это таким же образом - просто перейдите к сохраненному файлу настроек на последнем шаге мастера.

предлагая вам сохранить текущие настройки или нет. Если вы внесли обширные изменения и, возможно, захотите вернуться к ним позже, вам следует выбрать их сохранение.

Затем нажмите «Далее». Вам будет предложено импортировать набор настроек среды. Вверху будут параметры настройки среды по умолчанию, настроенные для каждого языка. В вашем случае вы должны выбрать C #.

Если вы хотите повторно импортировать сохраненные настройки, вы должны сделать это таким же образом - просто перейдите к сохраненному файлу настроек на последнем шаге мастера.

Вам будет предложено импортировать набор настроек среды. Вверху будут параметры настройки среды по умолчанию, настроенные для каждого языка. В вашем случае вы должны выбрать C #.

Если вы хотите повторно импортировать сохраненные настройки, вы должны сделать это таким же образом - просто перейдите к сохраненному файлу настроек на последнем шаге мастера.

Вам будет предложено импортировать набор настроек среды. Вверху будут параметры настройки среды по умолчанию, настроенные для каждого языка. В вашем случае вы должны выбрать C #.

Если вы хотите повторно импортировать сохраненные настройки, вы должны сделать это таким же образом - просто перейдите к сохраненному файлу настроек на последнем шаге мастера.

через интерфейс Добавляемый или StringBuilder класс:

Joiner.on(",").appendTo(someOutputStream, "a", "b", "c");

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

Joiner.on(", ").withKeyValueSeparator(":")
            .join(ImmutableMap.of(
            "today", "monday"
            , "tomorrow", "tuesday"))
8
ответ дан 29 November 2019 в 01:38
поделиться

Сначала вам понадобится функциональная библиотека для Java, которая предоставляет общие функторы и функциональные проекции типа fold. Я разработал и реализовал мощную (по достоинству), но простую такую библиотеку здесь: http://www.codeproject.com/KB/java/FunctionalJava.aspx (другие упомянутые библиотеки показались мне слишком сложными).

Тогда ваше решение будет выглядеть так:

Seq.of("","a",null,"b","",null,"c","").foldl(
    new StringBuilder(), //seed accumulator
    new Func2<StringBuilder,String,StringBuilder>(){
        public StringBuilder call(StringBuilder acc,String elmt) {
            if(acc.length() == 0) return acc.append(elmt); //do not prepend "," to beginning
            else if(elmt == null || elmt.equals("")) return acc; //skip empty elements
            else return acc.append(",").append(elmt);
        }
    }
).toString(); //"a,b,c"

Обратите внимание, что при применении fold единственная часть, которую действительно нужно продумать - это реализация для Func2.call, 3 строки кода, которые определяют оператор, принимающий аккумулятор и элемент и возвращающий аккумулятор (моя реализация учитывает пустые строки и нули, если убрать этот случай, то останется 2 строки кода).

А вот фактическая реализация Seq.foldl, Seq реализует Iterable:

public <R> R foldl(R seed, final Func2<? super R,? super E,? extends R> binop)
{
    if(binop == null)
        throw new NullPointerException("binop is null");

    if(this == EMPTY)
        return seed;

    for(E item : this)
        seed = binop.call(seed, item);

    return seed;
}
2
ответ дан 29 November 2019 в 01:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: