Существует ли типобезопасная реализация функции reduce для Java?

Мне часто нужно запускать reduce (также называемое foldl / foldr, в зависимости от вашего контекста) в java, чтобы агрегировать элементы Itterable.

Reduce принимает коллекцию / итерацию / и т.д., функцию двух параметров и необязательное начальное значение (в зависимости от деталей реализации). Функция последовательно применяется к элементу коллекции и к выходным данным предыдущего вызова reduce до тех пор, пока все элементы не будут обработаны, и возвращает окончательное значение.

Есть ли типобезопасная реализация reduce в каком-либо распространенном java api? Коллекции Google кажется, что они должны быть, но я не смог найти это. (возможно, потому что я не знаю, какие еще имена он использовал бы.)


person rcreswick    schedule 21.10.2008    source источник


Ответы (3)


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

public interface Reducer<A, T>
{
    public A foldIn(A accum, T next);
}

Затем, используя шаблон стратегии:

public class Reductor<A, T>
{
    private Reducer<A, T> worker;
    public Reductor<A, T>(Reducer<A, T> worker)
    {
        this.worker = worker;
    }

    public A fold(A rval, Iterator<T> itr)
    {
        while(itr.hasNext())
        {
            A rval = worker.foldIn(rval, itr.next());
        }
        return rval;
    }
}

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

Reductor r = new Reductor<A, T>(new Reducer<A, T>()
{
    public A foldIn(A prev, T next)
    {
        A rval;
       //do stuff...
       return rval;
     }
 }

 A fold = r.fold(new A(), collection.getIterator());

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

надеюсь это поможет.

person luke    schedule 21.10.2008
comment
это один из способов сделать это - я еще не уверен, что мне нужна общеприменимая версия сокращения, достаточно, чтобы оправдать затраты на разработку / тестирование / поддержку моей собственной версии. - person rcreswick; 21.10.2008
comment
хорошо сделано, но искажений, которые вам нужно сделать, чтобы сделать это в java, достаточно, чтобы заставить меня плакать. - person Steve B.; 22.10.2008
comment
Я думаю, что будет сопутствующая библиотека для Google Collections, которая предоставляет такие функциональные языковые инструменты, как этот, но на данный момент это лучший ответ, который я нашел. - person rcreswick; 06.11.2009

Основываясь на предложении Люка, вот законная реализация Java:

public interface Reducer<A,T>
{
    A foldIn(A accum, T next);
}

public static <T> T reduce(final Reducer<T,T> reducer, 
        final Iterable<? extends T> i)
{
    T result = null;
    final Iterator<? extends T> iter = i.iterator();
    if (iter.hasNext())
    {
        result = iter.next();
        while (iter.hasNext())
        {
            result = reducer.foldIn(result, iter.next());
        }
    }
    return result;
}

public static <A,T> A reduce(final Reducer<A,T> reducer, 
        final Iterable<? extends T> i, 
        final A initializer)
{
    A result = initializer;
    final Iterator<? extends T> iter = i.iterator();
    while (iter.hasNext())
    {
        result = reducer.foldIn(result, iter.next());
    }
    return result;
}
person Greg Haines    schedule 21.06.2010

Попробуйте воспользоваться пакетом функторов commons. Он всегда был в песочнице, но я думаю, что он сделает то, что вы хотите.

person sblundy    schedule 21.10.2008
comment
Это выглядит интересно, но не похоже, что это хорошо впишется в существующую библиотеку коллекций Java. Если больше ничего не появится, я углублюсь в это более глубоко. - person rcreswick; 21.10.2008
comment
Да, это сложно. Думаю, из него можно приготовить жареный картофель с жульеном. Похоже, что ключом к интеграции с коллекциями является класс IteratorToGeneratorAdapter. - person sblundy; 21.10.2008