Reputation: 5699
I've recently started working in Scala and that was my first real contact with a functional paradigm. Although I'm a big fan of Java and, I admit, it lacks functional paradigm sometimes.
That's why I recently started a a mini pet-project to see if such thing, to a degree, could be achieved in Java.
I started with a simple modification of an array list, and this is what I have so far:
An interface any collection needs to implement in order to offer applying functions to it's elements:
public interface Functionalizable<E> {
public Collection<E> apply(Function<E> f);
}
An interface that defines a method for applying the function on a single element:
public interface Function<E> {
public E apply(E e);
}
A concrete class backed by an array list that allows applying functions on it's elements:
public class FunctionArrayList<E> implements List<E>, Functionalizable<E> {
private List<E> list;
//implemented methods from `List` interface and ctors
@Override
public List<E> apply(Function<E> f) {
List<E> applied = new FunctionArrayList<>(this.list.size());
for (E e : this.list) {
applied.add(f.apply(e));
}
return applied;
}
}
I've written s small test method for Integer and it works OK:
Code:
List<Integer> listOfIntegersBefore = new FunctionArrayList<>();
listOfIntegersBefore.add(-1);
listOfIntegersBefore.add(0);
listOfIntegersBefore.add(1);
listOfIntegersBefore.add(2);
listOfIntegersBefore.add(3);
listOfIntegersBefore.add(4);
System.out.println("Before<Integer>: " + listOfIntegersBefore.toString());
List<Integer> listOfIntegersAfter = ((FunctionArrayList<Integer>) listOfIntegersBefore).apply(new Function<Integer>() {
@Override
public Integer apply(Integer e) {
return (e + 1);
}
});
System.out.println("After<Integer> : " + listOfIntegersAfter.toString());
Output:
Before<Integer>: [-1, 0, 1, 2, 3, 4]
After<Integer> : [0, 1, 2, 3, 4, 5]
However, when I try a tad more complex thing with List, I end up with much type-casting, which I don't like (and I'd like to avoid it as much as possible).
Code:
List<List<Integer>> listOfListOfIntegersBefore = new FunctionArrayList<>();
List<Integer> temp = new FunctionArrayList<>();
temp.add(1);
listOfListOfIntegersBefore.add(temp);
temp = new FunctionArrayList<>();
temp.add(1);
temp.add(2);
listOfListOfIntegersBefore.add(temp);
temp = new FunctionArrayList<>();
temp.add(1);
temp.add(2);
temp.add(3);
listOfListOfIntegersBefore.add(temp);
temp = new FunctionArrayList<>();
temp.add(1);
temp.add(2);
temp.add(3);
temp.add(4);
listOfListOfIntegersBefore.add(temp);
List<List<Integer>> listOfListOfIntegersAfter = (List<List<Integer>>) ((Functionalizable<List<Integer>>) listOfListOfIntegersBefore).apply(new Function<List<Integer>>() {
@Override
public List<Integer> apply(List<Integer> e) {
List<Integer> list = new FunctionArrayList<>(e);
return ((FunctionArrayList<Integer>) list).apply(new Function<Integer>() {
@Override
public Integer apply(Integer e) {
return (e + 1);
}
});
}
});
System.out.println("Before<List<Integer>>: " + listOfListOfIntegersBefore);
System.out.println("After<List<Integer>> : " + listOfListOfIntegersAfter);
Output:
Before<List<Integer>>: [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
After<List<Integer>> : [[2], [2, 3], [2, 3, 4], [2, 3, 4, 5]]
As I have already mentioned, I would like to avoid casting. Plus, Eclipse warns me about Type safety: Unchecked cast from List<List<Integer>> to Functionalizable<List<Integer>>
on this line:
List<List<Integer>> listOfListOfIntegersAfter = (List<List<Integer>>) ((Functionalizable<List<Integer>>) listOfListOfIntegersBefore).apply(new Function<List<Integer>>() {
...
}
Is there an elegant way to accomplish that?
Upvotes: 1
Views: 253
Reputation: 20221
You're making your own life hard.
List<List<Integer>> listOfListOfIntegersBefore = new FunctionArrayList<>();
[...]
((FunctionArrayList<Integer>) listOfIntegersBefore).apply
Why not store it as a FunctionArrayList
in the first place?
Of course you have to cast it this way.
Anyway, I find wrapping each list in a functional list a bit annoying, and I'd rather do it with simple static methods:
public interface F<S, T> { T apply(S s); }
public final class FunctionalStuff {
private FunctionalStuff() {}
public <S, T> static List<T> map(Collection<? extends S> collection,
F<? super S, ? extends T> func) {
final List<T> result = new ArrayList<T>(collection.size());
for (S source : collection)
result.add(func.apply(source));
return result;
}
public <S, T> static List<S> filter(Collection<? extends S> collection,
F<? super S, Boolean> predicate) {
final List<T> result = new ArrayList<T>(collection.size());
for (S source : collection)
if (predicate.apply(source))
result.add(source);
return result;
}
// etc etc.
}
Anyways, please note: I don't advise you to do functional style coding in Java. Wait for closures which will be added in Java 8.
Alternatively use a language that embraces functional style: Scala, Javascript, Clojure, Lisp, Mathematica, etc etc, there's a ton of them! Even c(++) seems less annoying at this than Java.
Upvotes: 2