I want to partially apply some arguments to a legacy method using Java 8's newly introduced function objects.
Here is the method in question:
/** * Appends a {@code character} a couple of {@code times} to a {@code string}. * * @return the string with the appended characters as a StringBuilder */ private static StringBuilder appendChar(char character, int times, String string) { StringBuilder strBuilder = new StringBuilder(string); for (int i = 0; i < times; i++) { strBuilder.append(character); } return strBuilder; }
This achieves what I wanted to do:
/* * Apply two arguments. The created function accepts a String and * returns a StringBuilder */ Function<String, StringBuilder> addEllipsis = appendToMe -> appendChar( '.', 3, appendToMe); /* * Apply one argument. This creates a function that takes another two * arguments and returns a StringBuilder */ BiFunction<String, Integer, StringBuilder> addBangs = (appendToMe, times) -> appendChar('!', times, appendToMe); // Create a function by applying one argument to another function Function<String, StringBuilder> addOneBang = appendToMe -> addBangs .apply(appendToMe, 1); StringBuilder res1 = addBangs.apply("Java has gone functional", 2); StringBuilder res2 = addOneBang.apply("Lambdas are sweet"); StringBuilder res3 = addEllipsis.apply("To be continued");
For a list of all of Java's predefined varieties of the function object have a look here.
Edit:
If you have a method with a lot of arguments, you can write your own kind of function:
/** * Represents a function that accepts three arguments and produces a result. * This is the three-arity specialization of {@link Function}. * * @param <T> * the type of the first argument to the function * @param <U> * the type of the second argument to the function * @param <V> * the type of the third argument to the function * @param <R> * the type of the result of the function * * @see Function */ @FunctionalInterface public interface TriFunction<T, U, V, R> { R apply(T t, U u, V v); }
Method accepting many arguments; you want to provide some of them:
private static boolean manyArgs(String str, int i, double d, float f) { return true; }
Here is how you use your custom function object:
/* * Pass one of the arguments. This creates a function accepting three * arguments. */ TriFunction<Integer, Double, Float, Boolean> partiallyApplied = (i, d, f) -> manyArgs("", i, d, f); /* * Provide the rest of the arguments */ boolean res4 = partiallyApplied.apply(2, 3.0, 4.0F); System.out.println("No time for ceremonies: " + res4);