18

I have a Consumer<T> that I'd like to convert into a Function<T, Void>.

I could achieve that by using

public <T> Function<T, Void> consumerToFunction(Consumer<T> consumer)
{
    return x -> {
        consumer.accept(x);
        return null;
    };
}

But I suspect that something like that might already exist in the JDK or perhaps in a common library.

GuiSim
  • 7,361
  • 6
  • 40
  • 50
  • No, don't think so, that looks right to me. That said -- why do you want this? `Function`s should generally be side-effect-free. – Louis Wasserman Apr 16 '15 at 20:11
  • 1
    `consumer::accept`? EDIT: [nope](http://ideone.com/NUGYOj), void cannot be converted to Void. Also, `Void` and `T` are in the wrong order. – user2357112 Apr 16 '15 at 20:11
  • I have a `Consumer` instance and the API I'm using requires a `Function`. The call ends up returning the `R` to me. I don't need that `R` and can safely ignore it. – GuiSim Apr 16 '15 at 20:12
  • @user2357112 that does not work. `Function x = stringConsumer::accept;` > `incompatible types: bad return type in method reference void cannot be converted to java.lang.Void` – GuiSim Apr 16 '15 at 20:13
  • Your solution looks fine to me. I don't know of any easier way to convert between those two function types. – Olivier Croisier Apr 16 '15 at 20:15
  • Can you describe the API you're using? Does that API want side effects in functions you're using? – Louis Wasserman Apr 16 '15 at 20:30
  • @LouisWasserman The API checks a bunch of validations and if they're good, the Function is called and the result returned. If they're not, an exception is thrown. – GuiSim Apr 16 '15 at 21:08
  • 1
    The only thing I would change, is to place the lambda expression right where you call `consumerToFunction` and get rid of that method… – Holger Apr 17 '15 at 08:14
  • 1
    My recent case for this was `java.util.concurrent.CompletableFuture.exceptionally(Function)` (ie a handler for an exception thrown from a completable future that has no return value). – Adrian Baker Apr 07 '18 at 00:55

2 Answers2

8

It looks like you need to adapt a Consumer<T> to a Function<T, R>. You have created a good example of the Adapter Pattern.

[T]he adapter pattern is a software design pattern that allows the interface of an existing class to be used from another interface.

You are letting a Consumer be used from a Function.

I know of no JDK built-in converter between functional interfaces, but this appears to be a good way of applying a standard pattern to solve your problem.

rgettman
  • 176,041
  • 30
  • 275
  • 357
1

A standard way doesn't exist, but this should do the trick:

Function<T, Void> adapt(final Consumer<T> consumer) {
    return t -> {
        consumer.accept(t);
        return null;
    };
}

This is following the Adapter Pattern mentioned in the accepted answer from @rgettman.

SeverityOne
  • 2,476
  • 12
  • 25