Java: Implement recursive cached from cached Function and cached BiFunction - java

TLDR: How to implement this function?
public static <T, R> Function<T, R> cachedRecursive(final BiFunction<T, Function<T,R>, R> bifunc) {
}
I need to somehow extract the second argument from the BiFunction so I can return a proper result for the function.
This project is for learning purposes, although I'm stuck with the last part of my task.
First part of the task is to create a Cache class extended from the LinkedHashMap, and this is my Implementation:
public class Cache<K,V> extends LinkedHashMap<K, V> {
private static int MaxSize;
public Cache (int maxSize) {
super(maxSize,1f,false);
MaxSize = maxSize;
}
public Cache () {
super();
}
public int getMaximalCacheSize () {
return MaxSize;
}
#Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > MaxSize;
}
}
As for the second part, it is to create a class for which the function definitions will be added:
public class FunctionCache {
private static class Pair<T, U> {
private T stored_t;
private U stored_u;
public Pair(T t, U u) {
stored_t = t;
stored_u = u;
}
public boolean equals(Object t) {
if (t == this) {
return true;
}
return t == stored_t;
}
public int hashCode () {
return stored_t.hashCode();
}
public T get_first() {
return stored_t;
}
public U get_second() {
return stored_u;
}
}
private final static int DEFAULT_CACHE_SIZE = 10000;
public static <T, R> Function<T, R> cached(final Function<T, R> func, int maximalCacheSize) {
Cache<T, R> cache = new Cache<T,R>(maximalCacheSize);
return input -> cache.computeIfAbsent(input, func);
}
public static <T, R> Function<T, R> cached(final Function<T, R> func) {
Cache<T, R> cache = new Cache<T,R>(DEFAULT_CACHE_SIZE);
return input -> cache.computeIfAbsent(input, func);
}
public static <T, U, R> BiFunction<T, U, R> cached(BiFunction<T, U, R> bifunc, int maximalCacheSize) {
Cache<T, R> cache = new Cache<T, R>(maximalCacheSize);
return (t, u) -> {
Pair<T,U> pairKey = new Pair<T,U>(t,u);
Function<Pair<T,U>, R> something = input -> {
return bifunc.apply(input.get_first(), input.get_second());
};
if (!cache.containsKey(pairKey.get_first())) {
R result = something.apply(pairKey);
cache.put(pairKey.get_first(), result);
return result;
} else {
return cache.get(pairKey.get_first());
}
};
}
public static <T, U, R> BiFunction<T, U, R> cached(BiFunction<T, U, R> bifunc) {
Cache<T, R> cache = new Cache<T, R>(DEFAULT_CACHE_SIZE);
return (t, u) -> {
Pair<T,U> pairKey = new Pair<T,U>(t,u);
Function<Pair<T,U>, R> something = input -> {
return bifunc.apply(input.get_first(), input.get_second());
};
if (!cache.containsKey(pairKey.get_first())) {
R result = something.apply(pairKey);
cache.put(pairKey.get_first(), result);
return result;
} else {
return cache.get(pairKey.get_first());
}
};
}
public static <T, R> Function<T, R> cachedRecursive(final BiFunction<T, Function<T,R>, R> bifunc) {
}
}
This is my problem:
public static <T, R> Function<T, R> cachedRecursive(final BiFunction<T, Function<T,R>, R> bifunc) {
}
I have absolutely no idea how to implement the cachedRecursive function, the previous functions are working with a simple fibonacci test perfectly, However the goal of this task is to implement the cachedRecursive function that takes a BiFunction with the first argument as the input and the second argument a function. Just to complete the code, this is the main class I used to test:
public class cachedFunction extends FunctionCache {
public static void main(String[] args) {
#SuppressWarnings({ "rawtypes", "unchecked" })
BiFunction<BigInteger, BiFunction, BigInteger> fibHelper = cached((n, f) -> {
if (n.compareTo(BigInteger.TWO) <= 0) return BigInteger.ONE;
return ((BigInteger) (f.apply(n.subtract(BigInteger.ONE), f)))
.add((BigInteger)f.apply(n.subtract(BigInteger.TWO), f));
}, 50000);
Function<BigInteger, BigInteger> fib = cached((n) -> fibHelper.apply(n,fibHelper));
System.out.println(fib.apply(BigInteger.valueOf(1000L)));
}
}

There are many drawbacks and mistakes in your code:
static size variables shared across different cache instances (therefore breaking it);
code duplication;
incorrect equals/hashCode contract implementation;
suppressing what should be fixed rather than suppressed;
the code is overly bloated;
and some minor ones (like _-containing lower-cased names, etc).
If you don't mind, I simplify it:
final class Functions {
private Functions() {
}
// memoize a simple "unknown" function -- simply delegates to a private encapsulated method
static <T, R> Function<T, R> memoize(final Function<? super T, ? extends R> f, final int maxSize) {
return createCacheFunction(f, maxSize);
}
// memoize a recursive function
// note that the bi-function can be converted to an unary function and vice versa
static <T, R> Function<T, R> memoize(final BiFunction<? super T, ? super Function<? super T, ? extends R>, ? extends R> f, final int maxSize) {
final Function<UnaryR<T, Function<T, R>>, R> memoizedF = memoize(unaryR -> f.apply(unaryR.t, unaryR.r), maxSize);
return new Function<T, R>() {
#Override
public R apply(final T t) {
// this is the "magic"
return memoizedF.apply(new UnaryR<>(t, this));
}
};
}
private static <T, R> Function<T, R> createCacheFunction(final Function<? super T, ? extends R> f, final int maxSize) {
final Map<T, R> cache = new LinkedHashMap<T, R>(maxSize, 1F, false) {
#Override
protected boolean removeEldestEntry(final Map.Entry eldest) {
return size() > maxSize;
}
};
return t -> cache.computeIfAbsent(t, f);
}
// these annotations generate proper `equals` and `hashCode`, and a to-string implementation to simplify debugging
#EqualsAndHashCode
#ToString
private static final class UnaryR<T, R> {
#EqualsAndHashCode.Include
private final T t;
#EqualsAndHashCode.Exclude
private final R r;
private UnaryR(final T t, final R r) {
this.t = t;
this.r = r;
}
}
}
And the test that tests both results and the memoization contract ("no recalculation, if memoized"):
public final class FunctionsTest {
#Test
public void testMemoizeRecursive() {
final BiFunction<BigInteger, Function<? super BigInteger, ? extends BigInteger>, BigInteger> fib = (n, f) -> n.compareTo(BigInteger.valueOf(2)) <= 0 ? BigInteger.ONE : f.apply(n.subtract(BigInteger.ONE)).add(f.apply(n.subtract(BigInteger.valueOf(2))));
#SuppressWarnings("unchecked")
final BiFunction<BigInteger, Function<? super BigInteger, ? extends BigInteger>, BigInteger> mockedFib = Mockito.mock(BiFunction.class, AdditionalAnswers.delegatesTo(fib));
final Function<BigInteger, BigInteger> memoizedFib = Functions.memoize(mockedFib, 1000);
final BigInteger memoizedResult = memoizedFib.apply(BigInteger.valueOf(120));
Mockito.verify(mockedFib, Mockito.times(120))
.apply(Matchers.any(), Matchers.any());
Assertions.assertEquals("5358359254990966640871840", memoizedResult.toString());
Assertions.assertEquals(memoizedResult, memoizedFib.apply(BigInteger.valueOf(120)));
Mockito.verifyNoMoreInteractions(mockedFib);
}
}

Related

Java 1.7. implementation of Function

I am using Java 1.7. (old I know, but I am working on a legacy application with a lot of dependencies).
I would like to implement the java.util.function.Function interface in 1.7.
I have the following so far, but am still getting compile errors:
public interface Function<T, R> {
R apply(T t);
public static <T, V, R> Function<V, R> compose(Function<? super V, ? extends T> before, Function<? super T, ? super R> after) {
return new CombiningFunction<T, V, R>(before, after);
}
public static <T, R, V> Function<T, V> andThen(Function<? super T, ? super R> before, Function<? super R, ? extends V> after) {
return new CombiningFunction<T, V, R>(before, after);
}
static <T> Function<T, T> identity() {
return new Function<T, T> {
T apply(T t) { return t; }
}
}
}
class CombiningFunction<T, V, R> implements Function<T, R> {
Function<T, V> first;
Function<V, R> second;
public R apply(T t) {
V intermediate = first.apply(t);
return second.apply(intermediate);
}
}
I need to add a constructor to CombiningFunction, but I am not sure how to add it, as I have tried the following:
public <V, T, R> CombiningFunction(Function<? super V,? extends T> before, Function<? super T,? super R> after) { }
but I get more compile errors on the types when I access the constructor.
Also, the following has errors:
return new Function<T, T> {
T apply(T t) { return t; }
}
Any help with this Function interface would be appreciated.
Compile Errors:
return new CombiningFunction<T, V, R>(before, after);
Expected 0 arguments but found 2
return new CombiningFunction<T, V, R>(before, after);
Expected 0 arguments but found 2
static <T> Function<T, T> identity() {
return new Function<T, T> {
T apply(T t) { return t; }
}
}
'(' or '[' expected ';' expected Cannot resolve symbol 't' Unexpected
token
I would like to use the Function as follows:
/**
* Creates Jwt token and other util methods.
*/
public class JwtTokenUtil {
private String SECRET_KEY = "secret-876123";
public String extractUserName(String token) {
return extractClaim(token, new Function<Claims, String>() {
#Override
public String apply(Claims claims) {
return claims.getSubject();
}
});
}
public Date extractExpiration(String token) {
return extractClaim(token, new Function<Claims, Date>() {
#Override
public Date apply(Claims claims) {
return claims.getExpiration();
}
});
}
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
/**
* Pass in user details, and get a Jwt
* #param userDetails
* #return
*/
public String generateToken(UserDetails userDetails) {
Map<String,Object> claims = new HashMap<>();
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String,Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10 hrs
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
public Boolean validteToken(String token, UserDetails userDetails) {
final String username = extractUserName(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
If you go to the OpenJDK repo you can find the source of the Function class. I am not up to date with available features and classes in Java 7 but I think this should fix some of your issues with Generics
https://github.com/openjdk/jdk/blob/6bab0f539fba8fb441697846347597b4a0ade428/src/java.base/share/classes/java/util/function/Function.java

Java Function in 1.7 (convert lambda expressions)

I am working on an old java application that uses Java 1.7. I would like to make use of the java.util.function.Function interface. However, this is only supported in Java 1.8+.
So I would like to write my own implementation in Java 1.7.
import java.util.Objects;
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v)); // lambda expression
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t)); // lambda expression
}
static <T> Function<T, T> identity() {
return t -> t; // lambda expression
}
}
The above gives me compile errors on the lambda expressions.
Question
How do I write the above lambda expressions in Java 1.7?
Since you can't actually create an interface with default methods, I think your best chance are static methods.
public interface Function<T, R> {
R apply(T t);
public static <T, V, R> Function<V, R> compose(Function<? super V, ? extends T> before, Function<? super T, ? super R> after) {
return new CombiningFunction<T, V, R>(before, after);
}
public static <T, R, V> Function<T, V> andThen(Function<? super T, ? super R> before, Function<? super R, ? extends V> after) {
return new CombiningFunction<T, V, R>(before, after);
}
static <T> Function<T, T> identity() {
return new Function<T, T> {
T apply(T t) { return t; }
}
}
}
class CombiningFunction<T, V, R> implements Function<T, R> {
Function<T, V> first;
Function<V, R> second;
public R apply(T t) {
V intermediate = first.apply(t);
return second.apply(intermediate);
}
}
But like KarelG mentions in the comments, it's really not advisable to do this; not to mention that this isn't nearly as elegant as in Java 8; after all, functional interfaces are pretty much geared towards lambdas, and if you don't have them, all usage will be as awkward as the implementation above.
You can use IntellijIdea to change it automatically, There is a result of IntellijIdea:
import java.util.Objects;
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return new Function<V, R>() {
#Override
public R apply(V v) {
return Function.this.apply(before.apply(v));
}
}; // lambda expression
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
Function<T, V> tvFunction = new Function<T, V>() {
#Override
public V apply(T t) {
return after.apply(Function.this.apply(t));
}
};
return tvFunction; // lambda expression
}
static <T> Function<T, T> identity() {
return new Function<T, T>() {
#Override
public T apply(T t) {
return t;
}
}; // lambda expression
}
}

Catching a generic exception

Problem
I am writing a Result type in Java, and I have found a need for it to have a method that performs an operation which may fail, and then encapulates the value or exception in a new Result object.
I had hoped this would work:
#FunctionalInterface
public interface ThrowingSupplier<R, E extends Throwable>
{
R get() throws E;
}
public class Result<E extends Throwable, V>
{
...
public static <E extends Throwable, V> Result<E, V> of(ThrowingSupplier<V, E> v)
{
try
{
return value(v.get());
}
catch(E e)
{
return error(e);
}
}
...
}
But Java cannot catch an exception defined by a type parameter.
I have also tried using instanceof, but that also cannot be used for generics. Is there any way I can implement this method?
Definitions
This is my result type before the addition of the of method. It's intended to be similar to both Haskell's Either and rust's Result, while also having a meaningful bind operation:
public class Result<E extends Throwable, V>
{
private Either<E, V> value;
private Result(Either<E, V> value)
{
this.value = value;
}
public <T> T match(Function<? super E, ? extends T> ef, Function<? super V, ? extends T> vf)
{
return value.match(ef, vf);
}
public void match(Consumer<? super E> ef, Consumer<? super V> vf)
{
value.match(ef, vf);
}
/**
* Mirror of haskell's Monadic (>>=)
*/
public <T> Result<E, T> bind(Function<? super V, Result<? extends E, ? extends T>> f)
{
return match(
(E e) -> cast(error(e)),
(V v) -> cast(f.apply(v))
);
}
/**
* Mirror of Haskell's Monadic (>>) or Applicative (*>)
*/
public <T> Result<E, T> then(Supplier<Result<? extends E, ? extends T>> f)
{
return bind((__) -> f.get());
}
/**
* Mirror of haskell's Applicative (<*)
*/
public Result<E, V> peek(Function<? super V, Result<? extends E, ?>> f)
{
return bind(v -> f.apply(v).then(() -> value(v)));
}
public <T> Result<E, T> map(Function<? super V, ? extends T> f)
{
return match(
(E e) -> error(e),
(V v) -> value(f.apply(v))
);
}
public static <E extends Throwable, V> Result<E, V> error(E e)
{
return new Result<>(Either.left(e));
}
public static <E extends Throwable, V> Result<E, V> value(V v)
{
return new Result<>(Either.right(v));
}
/**
* If the result is a value, return it.
* If it is an exception, throw it.
*
* #return the contained value
* #throws E the contained exception
*/
public V get() throws E
{
boolean has = match(
e -> false,
v -> true
);
if (has)
{
return value.fromRight(null);
}
else
{
throw value.fromLeft(null);
}
}
/**
* Upcast the Result's type parameters
*/
private static <E extends Throwable, V> Result<E, V> cast(Result<? extends E, ? extends V> r)
{
return r.match(
(E e) -> error(e),
(V v) -> value(v)
);
}
}
And the Either type, designed to closely mirror Haskell's Either:
/**
* A container for a disjunction of two possible types
* By convention, the Left constructor is used to hold an error value and the Right constructor is used to hold a correct value
* #param <L> The left alternative type
* #param <R> The right alternative type
*/
public abstract class Either<L, R>
{
public abstract <T> T match(Function<? super L, ? extends T> lf, Function<? super R, ? extends T> rf);
public abstract void match(Consumer<? super L> lf, Consumer<? super R> rf);
public <A, B> Either<A, B> bimap(Function<? super L, ? extends A> lf, Function<? super R, ? extends B> rf)
{
return match(
(L l) -> left(lf.apply(l)),
(R r) -> right(rf.apply(r))
);
}
public L fromLeft(L left)
{
return match(
(L l) -> l,
(R r) -> left
);
}
public R fromRight(R right)
{
return match(
(L l) -> right,
(R r) -> r
);
}
public static <L, R> Either<L, R> left(L value)
{
return new Left<>(value);
}
public static <L, R> Either<L, R> right(R value)
{
return new Right<>(value);
}
private static <L, R> Either<L, R> cast(Either<? extends L, ? extends R> either)
{
return either.match(
(L l) -> left(l),
(R r) -> right(r)
);
}
static class Left<L, R> extends Either<L, R>
{
final L value;
Left(L value)
{
this.value = value;
}
#Override
public <T> T match(Function<? super L, ? extends T> lf, Function<? super R, ? extends T> rf)
{
return lf.apply(value);
}
#Override
public void match(Consumer<? super L> lf, Consumer<? super R> rf)
{
lf.accept(value);
}
}
static class Right<L, R> extends Either<L, R>
{
final R value;
Right(R value)
{
this.value = value;
}
#Override
public <T> T match(Function<? super L, ? extends T> lf, Function<? super R, ? extends T> rf)
{
return rf.apply(value);
}
#Override
public void match(Consumer<? super L> lf, Consumer<? super R> rf)
{
rf.accept(value);
}
}
}
Example Usage
The main use of this is to convert exception-throwing operations into monadic ones. This allows for (checked) exception-throwing methods to be used in streams and other functional contexts, and also allows for pattern matching and binding on the return type.
private static void writeFiles(List<String> filenames, String content)
{
filenames.stream()
.map(
(String s) -> Result.of(
() -> new FileWriter(s) //Open file for writing
).peek(
(FileWriter f) -> Result.of(
() -> f.write(content) //Write file contents
)
).peek(
(FileWriter f) -> Result.of(
() -> f.close()) //Close file
)
).forEach(
r -> r.match(
(IOException e) -> System.out.println("exception writing to file: " + e), //Log exception
(FileWriter f) -> System.out.println("successfully written to file '" + f + "'") //Log success
)
);
}
Just use the optimistic assumption that the interface fulfills the contract, as ordinary Java code will always do (enforced by the compiler). If someone bypasses this exception-checking, it’s not your responsibility to fix that:
public static <E extends Exception, V> Result<E, V> of(ThrowingSupplier<V, E> v) {
try {
return value(v.get());
}
catch(RuntimeException|Error x) {
throw x; // unchecked throwables
}
catch(Exception ex) {
#SuppressWarnings("unchecked") E e = (E)ex;
return error(e);
}
}
Note that even the Java programming language agrees that it is okay to proceed with this assumption, e.g.
public static <E extends Exception, V> Result<E, V> of(ThrowingSupplier<V, E> v) throws E {
try {
return value(v.get());
}
catch(RuntimeException|Error x) {
throw x; // unchecked throwables
}
catch(Exception ex) {
throw ex; // can only be E
}
}
is valid Java code, as under normal circumstances, the get method can only throw E or unchecked throwables, so it is valid to rethrow ex here, when throws E has been declared. We only have to circumvent a deficiency of the Java language when we want to construct a Result parameterized with E.
You need access to the class of the exception and then use some generics in the catch block.
One simple way is to pass the Class<E> class to the Result.of method:
public static <E extends Throwable, V> Result<E, V> of(
ThrowingSupplier<V, E> v,
Class<E> errorType) {
try {
return value(v.get());
} catch(Throwable e) {
if (errorType.isInstance(e)) {
return error(errorType.cast(e));
}
throw new RuntimeException(e); // rethrow as runtime?
}
}
Usage:
Result.of(() -> new FileWriter(s), IOException.class)
Class.isInstance is the dynamic equivalent of the instanceof static operator, while Class.cast is the same as statically casting: (E) e, except that we don't get a warning from the compiler.
EDIT: You need to think what to do when the catched Throwable is not of the type of the exception you are expecting. I've wrapped it in a RuntimeException and have rethrown it. This allows to keep using a fluent style for your monad, but is not transparent any more, as now any exception is wrapped in an unchecked exception. Maybe you could add a 3rd argument to Result.of to handle this specific case...
Update: this seems not to work at all. I'm keeping it here for now because I've linked to is elsewhere, and because it uses a method provided in other accepted answers, which I would like to continue to investigate.
Using Federico's answer and the answer linked in the comment, I have deduced a solution with the same method signature as the original problem, and I have created a class which encapsulates this functionality for future use.
The Result implementation:
public class Result<E extends Exception, V>
{
...
public static <E extends Exception, V> Result<E, V> of(ThrowingSupplier<V, E> v)
{
try
{
return value(v.get());
}
catch(Exception e)
{
Class<E> errType = Reflector.getType();
if (errType.isInstance(e))
{
return error(errType.cast(e));
}
else
{
throw (RuntimeException) e;
}
}
}
...
}
And the Reflector:
import java.lang.reflect.ParameterizedType;
/**
* This class only exists to provide a generic superclass to {#link Reflector}
* #param <E> The type for the subclass to inspect
*/
abstract class Reflected<E>
{ }
/**
* This class provides the ability to obtain information about its generic type parameter.
* #param <E> The type to inspect
* #author
*/
#Deprecated
public class Reflector<E> extends Reflected<E>
{
/**
* Returns the class corresponding to the type {#code <E>}.
* #param <E> The type to inspect
* #return The class corresponding to the type {#code <E>}
*/
public static <E> Class<E> getType()
{
return new Reflector<E>().getParameterType();
}
private Reflector() {}
private Class<E> getParameterType()
{
final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
return (Class<E>) type.getActualTypeArguments()[0];
}
}

How to perform Java lambda function decomposition

I have been learning how to do composition of lambda expressions using the andThen and compose functions, for example:
Function<SceneObject> transform = scaleX2.andThen(scaleY2).andThen(rotateZ45);
Is there a way to remove one of the steps in the resulting function?
So, in the above example transform.decompose(scaleY2) would result in transform = scaleX2.andThen(rotateZ45).
Not with that code. Function.andThen is implemented by constructing a lambda expression, which completely hides the details of the two functions used to construct it.
An alternative approach would be to use your own type, say Transform<T, R> which can wrap the equivalent function, and can then support a decompose operation.
import java.util.Optional;
#FunctionalInterface
public interface Transform<T, R> {
class AndThen<T, R, S> implements Transform<T, S> {
final Transform<T, R> first;
final Transform<R, S> second;
AndThen(Transform<T, R> first, Transform<R, S> second) {
this.first = first;
this.second = second;
}
#Override
public S apply(T t) {
return second.apply(first.apply(t));
}
#Override
public <U> Optional<Transform<T, U>> decomposeFst() {
return Optional.of((Transform<T, U>)first);
}
#Override
public <U> Optional<Transform<U, S>> decomposeSnd() {
return Optional.of((Transform<U, S>)second);
}
}
default <S> Transform<T, S> andThen(Transform<R, S> next) {
return new AndThen<T, R, S>(this, next);
}
R apply(T t);
default <S> Optional<Transform<T, S>> decomposeFst() {
return Optional.empty();
}
default <S> Optional<Transform<S, R>> decomposeSnd() {
return Optional.empty();
}
static void main(String[] args) {
final Transform<Double, String> f = Object::toString;
final Transform<String, Integer> g = String::length;
final Transform<Double, Integer> h = f.andThen(g);
final int i = h.apply(1.234);
final Optional<Transform<Double, String>> f2 = h.<String>decomposeFst();
final Optional<Transform<String, Integer>> g2 = h.<String>decomposeSnd();
final String s = f2.get().apply(1.234);
final int j = g2.get().apply(s);
System.out.println(s + " : " + j);
}
}

How can I implement Function and BiFunction at the same time?

I created a class GenericFunction that implements Function and BiFunction. But it cannot be compiled.
public class GenericFunction<T, U, R> implements
Function<T, R>, BiFunction<T, U, R> {
#Override
public R apply(T t, U u) {
return null;
}
#Override
public R apply(T t) {
return null;
}
}
The error message is:
src\obscure\test\GenericFunction.java:6: error:
types BiFunction<T,U,R> and Function<T,R> are incompatible;
both define andThen(java.util.function.Function<? super R,? extends V>),
but with unrelated return types
public class GenericFunction<T, U, R> implements
^
where T,U,R are type-variables:
T extends Object declared in class GenericFunction
U extends Object declared in class GenericFunction
R extends Object declared in class GenericFunction
1 error
How can I do that?
I have no idea why you would want something like this, but it seemed like an interesting challenge...
The main problem is that both Function & BiFunction implement a default andThen function, both having the exact same signature, so your class doesn't know which to call. You just have to provide your own implementation, then its not ambiguous anymore. However the implementation is tricky.
The java docs say the method:
Returns a composed function that first applies this function to its input, and then applies the after function to the result.
... so that means returning a new GenericFunction, where both apply methods are now compositions.
I give you this monstrosity:
public class GenericFunction<T, U, R> implements Function<T, R>, BiFunction<T, U, R> {
#Override
public R apply(T t, U u) {
return null;
}
#Override
public R apply(T t) {
return null;
}
#Override
public <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
return new GenericFunctionAndThen<>(after);
}
private class GenericFunctionAndThen<V> extends GenericFunction<T, U, V> {
private final Function<? super R, ? extends V> after;
public GenericFunctionAndThen(Function<? super R, ? extends V> after) {
this.after = after;
}
#Override
public V apply(T t) {
return after.apply(GenericFunction.this.apply(t));
}
#Override
public V apply(T t, U u) {
return after.apply(GenericFunction.this.apply(t, u));
}
}
}
This uses the most obscure feature of Java that I know of... I don't even know the name! ClassName.this is used in a nested class to refer to a method (or field) in the enclosing instance, if the method is shadowed.
Extending from #romacafe's answer, one thing that I don't like about it is that GenericFunctionAndThen extends GenericFunction without reusing any of the behaviour of its super class – which looks to me as a bad smell.
Things will be cleaner if you implemented GenericFunction as an interface instead:
public interface GenericFunction<T, U, R> extends Function<T, R>, BiFunction<T, U, R> {
#Override
default <V> GenericFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
return new GenericFunction<T, U, V>() {
#Override
public V apply(final T t, final U u) {
return after.apply(GenericFunction.this.apply(t, u));
}
#Override
public V apply(final T t) {
return after.apply(GenericFunction.this.apply(t));
}
};
}
}
This way you have a simple implementation of the generic behaviour (the andThen method), and you can implement your specific behaviour (the 2 apply methods) in a specific class without relying on inheritance.

Categories