Created
December 12, 2011 23:25
-
-
Save msfroh/1469633 to your computer and use it in GitHub Desktop.
Functional Programming in Java Part 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final Function2<Integer, Integer, Integer> add = | |
new Function2<Integer, Integer, Integer>() { | |
@Override | |
public Integer apply(Integer i1, Integer i2) { | |
return i1 + i2; | |
} | |
}; | |
// The next two lines output the same thing | |
System.out.println("4 + 5 = " + add.apply(4, 5)); | |
System.out.println("4 + 5 = " + add.curry().apply(4).apply(5)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
output = ListUtils.map(new Function1<Integer, Integer>() { | |
@Override | |
public Integer apply(Integer i1) { | |
return i1 * 2; | |
} | |
}).apply(values); | |
System.out.println(output); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FoldExamples { | |
public static void main(final String[] args) { | |
List<Integer> values = Arrays.asList(8, 6, 7, 5, 3, 0, 9); | |
Integer output; | |
// Find the maximum number | |
output = ListUtils.foldLeft(new Function2<Integer, Integer, Integer>() { | |
@Override | |
public Integer apply(Integer i1, Integer i2) { | |
return i1 < i2 ? i2 : i1; | |
} | |
}).apply(Integer.MIN_VALUE).apply(values); | |
System.out.println(output); | |
// Find the sum | |
output = ListUtils.foldLeft(new Function2<Integer, Integer, Integer>() { | |
@Override | |
public Integer apply(Integer i1, Integer i2) { | |
return i1 + i2; | |
} | |
}).apply(0).apply(values); | |
System.out.println(output); | |
// Treat list elements as digits and combine to produce | |
// the resulting integer. | |
output = ListUtils.foldLeft(new Function2<Integer, Integer, Integer>() { | |
@Override | |
public Integer apply(Integer i1, Integer i2) { | |
return i1 * 10 + i2; | |
} | |
}).apply(0).apply(values); | |
System.out.println(output); | |
// Concatenate the elements together as a string separated by commas | |
String sOutput; | |
sOutput = ListUtils.foldLeft(new Function2<String, String, Integer>() { | |
@Override | |
public String apply(String i1, Integer i2) { | |
final String sep = (i1.length() > 0) ? "," : ""; | |
return i1 + sep + i2.toString(); | |
} | |
}).apply("").apply(values); | |
System.out.println(sOutput); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class StringLength { | |
public Integer apply(final String input) { | |
return input.length(); | |
} | |
} | |
// The following outputs 5 | |
System.out.println(new StringLength().apply("hello")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class FunctionStringToInteger { | |
public Integer apply(final String input); | |
} | |
final FunctionStringToInteger stringLength = new FunctionStringToInteger() { | |
@Override | |
public Integer apply(final String input) { | |
return input.length(); | |
} | |
}; | |
// The following outputs 5 | |
System.out.println(stringLength.apply("hello")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ListUtils { | |
/* ... previous definition of map ... */ | |
// Untyped (raw) foldLeft instance | |
private static final Function3 rawFoldLeft = | |
new Function3<Object, Function2, Object, List>() { | |
@Override | |
public Object apply(final Function2 func, final Object seed, final List list) { | |
Object accumulated = seed; | |
for (Object t : list) { | |
accumulated = func.apply(accumulated, t); | |
} | |
return accumulated; | |
} | |
}; | |
// "Factory" method that returns foldLeft function instance with | |
// appropriate generic type parameters. | |
public static <R, T1> Function3<R, Function2<R, R, T1>, R, List<? extends T1>> | |
foldLeftFunc(Class<R> returnClass, | |
Class<T1> inputClass) { | |
return rawFoldLeft; | |
} | |
// Convenient partial application of foldLeft function where type parameters | |
// are supplied by the transformation function. | |
public static <R, T1> Function2<R, R, List<? extends T1>> | |
foldLeft(final Function2<R, R, T1> function2) { | |
final Function3<R, Function2<R, R, T1>, R, List<? extends T1>> | |
foldLeftFunc = rawFoldLeft; | |
return foldLeftFunc.apply(function2); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class ListUtils { | |
// Untyped (raw) map function instance | |
private static final Function2 rawMap = | |
new Function2<List, Function1, List>() { | |
@Override | |
public List apply(Function1 func, List list) { | |
List outputList = new ArrayList(list.size()); | |
for (Object t : list) { | |
outputList.add(func.apply(t)); | |
} | |
return outputList; | |
} | |
}; | |
// "Factory" method that returns map function instance with | |
// appropriate generic type parameters. | |
public static <R, T1> Function2<List<R>, Function1<R, T1>, List<? extends T1>> | |
mapFunc(Class<R> returnClass, | |
Class<T1> inputClass) { | |
return rawMap; | |
} | |
// Convenient partial application of map, where type parameters | |
// are taken from the transformation function. | |
public static <R, T1> | |
Function1<List<R>, List<? extends T1>> map(final Function1<R, T1> f1) { | |
final Function2<List<R>, | |
Function1<R, T1>, | |
List<? extends T1>> mapFunc = rawMap; | |
return mapFunc.apply(f1); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class MapExamples { | |
// Very bad performance if "values" is a LinkedList | |
public static List<Integer> | |
doubleListWithIndexes(final List<Integer> values) { | |
List<Integer> doubledValues = new ArrayList<Integer>(); | |
for (int i = 0; i < values.size(); i++) { | |
doubledValues.add(values.get(i) * 2); | |
} | |
return doubledValues; | |
} | |
// Okay. Popular in the pre-1.5 days of Java. | |
public static List<Integer> | |
doubleListWithIteratorWhile(final List<Integer> values) { | |
List<Integer> doubledValues = new ArrayList<Integer>(); | |
Iterator<Integer> iter = values.iterator(); | |
while (iter.hasNext()) { | |
doubledValues.add(iter.next() * 2); | |
} | |
return doubledValues; | |
} | |
// Like the example above, but combines two lines into one. | |
// May be less readable than the "while" version. | |
public static List<Integer> | |
doubleListWithIteratorFor(final List<Integer> values) { | |
List<Integer> doubledValues = new ArrayList<Integer>(); | |
for (Iterator<Integer> iter = values.iterator(); iter.hasNext();) { | |
doubledValues.add(iter.next() + 2); | |
} | |
return doubledValues; | |
} | |
// The standard way to do in Java 1.5 or later | |
public static List<Integer> | |
doubleListWithForeach(final List<Integer> values) { | |
List<Integer> doubledValues = new ArrayList<Integer>(); | |
for (Integer value : values) { | |
doubledValues.add(value * 2); | |
} | |
return doubledValues; | |
} | |
public static void main(final String[] args) { | |
List<Integer> values = Arrays.asList(1, 2, 3, 4, 5); | |
List<Integer> output; | |
output = doubleListWithIndexes(values); | |
System.out.println(output); | |
output = doubleListWithIteratorWhile(values); | |
System.out.println(output); | |
output = doubleListWithIteratorFor(values); | |
System.out.println(output); | |
output = doubleListWithForeach(values); | |
System.out.println(output); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class Function2<R, T1, T2> { | |
/* ... previous definition of apply(T1,T2) and curry() ... */ | |
public Function1<R, T2> apply(final T1 t1) { | |
return curry().apply(t1); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final Function1<Integer, Integer> addFour = add.apply(4); | |
System.out.println("4 + 5 = " + addFour.apply(5)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment