Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent to map (from haskell) in Java 7

Tags:

java

haskell

In Haskell there is a function called map, which takes a List of Type A and a function f, mapping values of type A to values of type B. It returns a list of type B, such that each element of the result list originates from a call of f to a value in the input list.

For example, given

  • a list m = ['a', 'b', 'c'],
  • and a function f = {'a' -> 1, 'b' -> 2, 'c' -> 3},
  • then map(m, f) = [1, 2, 3].

Is there a library, usable with Java 7, that offers something like the map function? I already viewed apache CollectionUtils and found things like forAllDo and transform, but they don't allow retuning a collection of a completely different type. Googling for other libraries failed for the same reason.

To be clear: I know how to solve the problem by myself, but I strongly feel that there must already exist a good library that performs this task more generally.

Bonus question: Is there some equivalent to Haskell functors (i.e. move from collections to iterables) usable in Java 7? Further explanation: Is there a map function which takes an Iterable<A> instead of Collection<A> and returns an Iterable<B> instead of Collection<B> (provided by a fitting function f)?

like image 555
user3389669 Avatar asked Dec 02 '15 11:12

user3389669


2 Answers

You are asking for Java 7 (with Java 8 it's easier):

You can use Guava and there specifically FluentIterable

    final List<String> strings = Arrays.asList("a", "b", "c");
    final List<Integer> integers = FluentIterable
            .from(strings)
            .transform(new Function<String, Integer>() {
                @Nullable
                @Override
                public Integer apply(@Nullable String input) {
                    return input.equals("a") ? 1 : input.equals("b") ? 2 : input.equals("c") ? 3 : -1;
                }
            })
            .toList();

Bonus question: A collection is an iterable :-)

like image 183
spa Avatar answered Oct 03 '22 01:10

spa


Functional transformations were added to Java 8 and they are not available for Java 7. For example, a map function that transforms a String to an integer looks like this Java 8

List<String> list = Arrays.asList("1","2","3");
List<Integer> nums = list.stream().map(Integer::parseInt).collect(Collectors.toList());

Unlike Haskell, Java collections are strict, however Streams ( Java 8) are lifted ( ~ lazy).

There are libraries that support higher order functions for Java 7 like Guava. Guava has a transform function that transforms T -> U, for ex:

Collection<Integer> ints = Collections2.transform(list, new Function<String, Integer>() {
        @Override
        public Integer apply(String s) {
            return Integer.parseInt(s);
        }
    });

But as you can tell ,due to the lack of lambda expressions in Java 7, it doesn't look concise

like image 33
Sleiman Jneidi Avatar answered Oct 02 '22 23:10

Sleiman Jneidi