Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java join collections using functor

2 collections are given with the same number of elements, say List<String>. What are elegant ways in JAVA to apply a functor on each 2 elements of collections with corresponding indexes?

Say, one example could be:
List<String> = { "APPLE", "PEAR" };
List<String> = { "BANANA", "ORANGE" };

A predicate that joins string together will result in the following List<String>:
List<String> = { "APPLEBANANA", "PEARORANGE" };

like image 508
Leonid Avatar asked Nov 28 '25 03:11

Leonid


2 Answers

Akin to the functors found in Apache Commons Collections, I have created binary equivalents in the past.

For your situation, a binary transformer type object, which takes to two input objects and returns a single object, could be used. Here is some sample code that's conveys my approach:

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

HTH

like image 53
Brent Worden Avatar answered Nov 29 '25 16:11

Brent Worden


A quick driver of this showed it to work. Not responsible for all test cases. :-)

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;

}

If you need something generic, you would need to know they ahve a way that they can be joined

 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 - here's a working example based off @Brents (superior) example. Props to him for illustrating this pattern better than I did.

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


    }
}
like image 37
corsiKa Avatar answered Nov 29 '25 15:11

corsiKa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!