Объединение Java-коллекций с использованием функтора - PullRequest
3 голосов
/ 11 марта 2011

2 коллекции даны с одинаковым количеством элементов, скажем, List<String>.Каковы элегантные способы применения JAVA функтора для каждых 2 элементов коллекций с соответствующими индексами?

Скажем, одним примером может быть:
List<String> = { "APPLE", "PEAR" };
List<String> = { "BANANA", "ORANGE" };

Предикат, объединяющий строку, приведет к следующему List<String>:
List<String> = { "APPLEBANANA", "PEARORANGE" };

Ответы [ 4 ]

3 голосов
/ 11 марта 2011

Сродни функторам, найденным в коллекциях Apache Commons, я создал двоичные эквиваленты в прошлом.

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

// tranformer
interface BinaryTransformer<X, Y, Z> {
  Z transform(X a, Y b);
}

// implementation for your problem
class ConcatTransformer implements BinaryTransformer<String, String, String> {
  public String transform(String a, String b) {
    return a + b;
  }
}

// general use transformer
class BinaryListUtils {
  public static <X, Y, Z> List<Z> collect(List<X> aList, List<Y> bList, BinaryTransformer<X, Y, Z> t) {
    List<Z> ret = new ArrayList<Z>(aList.size());
    Iterator<X> aIter = aList.iterator();
    Iterator<Y> bIter = bList.iterator();
    while(aIter.hasNext()) {
      ret.add(t.transform(aIter.next(), bIter.next()));
    }
  }
}

НТН

2 голосов
/ 11 марта 2011

Быстрый драйвер показал, что он работает. Не несет ответственности за все тестовые случаи. : -)

List<String> combineListsHorizontally(List<String> a, List<String> b) {
    assert a.size() == b.size(); // just avoids some checks

    List<String> result = new ArrayList<String>(a.size());

    Iterator<String> itera = a.iterator();
    Iterator<String> iterb = b.iterator();

    for(int i = 0; i < a.size(); i++) {
        String combined = itera.next() + iterb.next();
        result.add(combined);
    }
    return result;

}

Если вам нужно что-то общее, вам нужно знать, как они могут быть объединены

 List<E> combineListsHorizontally(List<E> a, List<E> b) {
        assert a.size() == b.size(); // just avoids some checks

        List<E> result = new ArrayList<E>(a.size());

        Iterator<E> itera = a.iterator();
        Iterator<E> iterb = b.iterator();

        for(int i = 0; i < a.size(); i++) {
            E combined = new MagicCombiner<E>(a,b).get(); // define this line yourself
            result.add(combined);
        }
        return result;

    }

///////////////// EDIT - вот рабочий пример, основанный на примере @Brents (вышестоящий). Рекомендую ему лучше иллюстрировать эту модель, чем я.

import java.util.*;

/**
 * Compile: "javac BinaryListUtils"
 * Usage: "java BinaryListUtils"

 C:\Documents and Settings\user\My Documents>javac BinaryListUtils.java

 C:\Documents and Settings\user\My Documents>java BinaryListUtils
 APPLEBANANA
 PEARORANGE

 C:\Documents and Settings\user\My Documents>
 */

// general use transformer
class BinaryListUtils {

    // tranformer
    static interface BinaryTransformer<X, Y, Z> {
        Z transform(X a, Y b);
    }

    // implementation for your problem
    static class ConcatTransformer implements BinaryTransformer<String, String, String> {
        public String transform(String a, String b) {
            return a + b;
        }
    }

    public static <X, Y, Z> List<Z> collect(List<X> aList, List<Y> bList, BinaryTransformer<X, Y, Z> t) {
        List<Z> ret = new ArrayList<Z>(aList.size());
        Iterator<X> aIter = aList.iterator();
        Iterator<Y> bIter = bList.iterator();
        while(aIter.hasNext()) {
            ret.add(t.transform(aIter.next(), bIter.next()));
        }
        return ret;
    }

    public static void main(String[] args) {

        List<String> aList = new ArrayList<String>();
        List<String> bList = new ArrayList<String>();

        aList.add("APPLE");
        aList.add("PEAR");

        bList.add("BANANA");
        bList.add("ORANGE");

        ConcatTransformer ct = new ConcatTransformer();

        List<String> cList = BinaryListUtils.collect(aList,bList,ct);

        for(String s : cList) System.out.println(s);


    }
}
1 голос
/ 11 марта 2011

То, что вы просите, не является предикатом. Это делает преобразование в списках, упакованных вместе. Общий способ сделать это - написать итеративную застежку-молнию, которая заархивирует два списка в итерируемую пару, а затем применяет преобразование к парам.

Сначала я подумал, что вы спрашиваете о пересечении двух коллекций, которые поставляются в коллекции Guava как Sets.intersection (Set, Set).

0 голосов
/ 11 марта 2011

Я думаю, что ваша лучшая ставка здесь будет делать это итеративно. Я не могу придумать ни одного основного Java API, который может это сделать.

public List<String> predicate(List<String> list1, List<String> list2) {
    List<String> list = new ArrayList<String>();

    for(int i = 0; i < list1.size(); i++) {
        list.add(new StringBuilder(list1.get(i)).append(list2.get(i)).toString());
    }

    return list;
}

Не скомпилировал / запустил его. Удачи.

...