Chapter 7. Using tuples

Table of Contents

7.1. Pairs, Triples and Quaduples
7.2. Using zip
7.3. Using unzip
7.4. Using zipWith

7.1. Pairs, Triples and Quaduples

Tuples are groups of data. Sometimes you have pieces of data that you would like to group together, but do not want to create an extra class just for that purpose. Tuples can come in handy in those types of situations. FunctionalJ provides classes to group together two, three or four objects, respectively Pair, Triple and Quadruple.

Each of these classes has a constructor that accepts the objects to be grouped together. You can also use the default constructor and use setters to supply the objects. Getters allow the objects to be retrieved. The properties that correspond to the contained objects are first, second, third and fourth.

The tuple classes also implement the equals, hashCode and compareTo methods, using those methods on the contained objects to determine the result. In the case of compareTo, tuples are sorted according to the contained objects, in their grouping order.

7.2. Using zip

The Tuples class contains methods that produce tuples. One of these methods is zip, which consists in taking collections of objects and grouping together corresponding objects, returning a list of tuples as a result. If the collections are not of the same length, the length of the collection with the least number of elements is used, and trailing elements in the other collections are ignored.

zip([a1,a2,..,an],[b1,b2,..,bn],..) = [(a1,b1,..),(a2,b2,..),..,(an,bn,..)]

For example:

List<String> strings = Arrays.asList("A", "B", "C", "D");
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

List<Pair<String,Integer>> pairs = Tuples.zip(strings, integers);
assertEquals(pairs.toString(), "[(A, 1), (B, 2), (C, 3), (D, 4)]");

7.3. Using unzip

The reverse operation of zip is unzip, which takes a collection of tuples and returns a tuple that contains the original lists:

unzip([(a1,b1,..),(a2,b2,..),..,(an,bn,..)]) = ([a1,a2,..,an],[b1,b2,..,bn],..)

For example:

List<String> strings = Arrays.asList("A", "B", "C", "D");
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<Pair<String,Integer>> pairs = Tuples.zip(strings, integers);

Pair<List<String>,List<Integer>> lists = Tuples.unzipPairs(pairs);

assertEquals(lists.getFirst(), strings);
assertEquals(lists.getSecond(), integers);
Note that the unzip methods are named according to the type of the tuples contained in the collection. Indeed, each method accepts a Collection as a parameter, so they must have different names.

7.4. Using zipWith

To take corresponding objects from collections, perform some computation on them, and obtain the results, you can use the zipWith method. This method takes a function and collections of objects. The function must accept as many parameters as there are collections. Then, the corresponding objects from each collection are used as parameters to call the function, and a list of the results is returned.

zipWith(f, [a1,a2,..,an], [b1,b2,..,bn]) = [f(a1,b1), f(a2,b2), .., f(an,bn)]

For example:

List<String> firstNames = Arrays.asList("John", "Jane", "Abby", "Paul");
List<String> lastNames = Arrays.asList("Smith", "Doe");

Function2<String,String,String> concat = new Function2Impl<String,String,String>()
{
    public String call(String p_firstName, String p_lastName)
    {
        return p_firstName + " " + p_lastName;
    }
};

List<String> names = Tuples.zipWith(concat, firstNames, lastNames);
assertEquals(names, Arrays.asList("John Smith", "Jane Doe"));
Notice that again, trailing elements of the longer list are ignored.

The zipWith method is in fact a generalization of the zip method. Indeed, zip calls zipWith with a function that returns a tuple containing the objects that were passed as parameters.