A while ago I wanted to perform a certain operation for every subsequent pair of elements in collection, i.e. for list [1, 2, 3, 4, 5] I wanted to do something with pairs [(1, 2), (2, 3), (3, 4), (4, 5)]. In Haskell that would be easy:
The problem is, I needed this stuff in my Android app, which means Java. The easiest thing to write would be obviously:
1234567
List<T>list;for(inti=1;i!=list.size();++i){Tleft=list.get(i-1);Tright=list.get(i);// do something useful}
But where’s the fun with that? Fortunately, there is Guava. It doesn’t have the zip or init functions, but it provides tool to write them yourself – the AbstractIterator. Tl;dr of the documentation: override one method returning an element or returning special marker from endOfData() method result.
The tail can be achieved simply by calling the Iterables.skip:
1234
publicstatic<T>Iterable<T>getTail(Iterable<T>iterable){Preconditions.checkArgument(iterable.iterator().hasNext(),"Iterable cannot be empty");returnIterables.skip(iterable,1);}
For init you could write similar function:
1234
publicstatic<T>Iterable<T>getInit(finalIterable<T>iterable){Preconditions.checkArgument(iterable.iterator().hasNext(),"Iterable cannot be empty");returnIterables.limit(iterable,Iterables.size(iterable));}
But this will iterate through the entire iterable to count the size. We don’t need the count however, we just need to know if there is another element in the iterable. Here is more efficient solution:
12345678910111213141516171819202122
publicstatic<T>Iterable<T>getInit(finalIterable<T>iterable){Preconditions.checkArgument(iterable.iterator().hasNext(),"Iterable cannot be empty");returnnewIterable<T>(){@OverridepublicIterator<T>iterator(){finalIterator<T>iterator=iterable.iterator();returnnewAbstractIterator<T>(){@OverrideprotectedTcomputeNext(){if(iterator.hasNext()){Tt=iterator.next();if(iterator.hasNext()){returnt;}}returnendOfData();}};}};}
All methods used together look like this:
1234
List<T>list;for(Pair<T,T>zipped:zip(getInit(list),getTail(list))){// do something useful}