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.
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)]");
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.
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.