16

I'm looking for the inverse of Supplier<T> in Guava. I hoped it would be called Consumer – nope – or Sink – exists, but is for primitive values.

Is it hidden somewhere and I'm missing it?

I'd like to see it for the same kinds of reasons that Supplier is useful. Admittedly, uses are less common, but many of the static methods of Suppliers, for example, would apply in an analogous way, and it would be useful to express in one line things like "send this supplier every value in this iterable".

In the meantime, Predicate and Function<T,Void> are ugly workarounds.

Alice Purcell
  • 12,622
  • 6
  • 51
  • 57
BeeOnRope
  • 60,350
  • 16
  • 207
  • 386
  • 5
    Probably not helpful but there is a Consumer in... Java 8. – JB Nizet Feb 05 '13 at 08:23
  • You might actually be looking for a binary function, which could then be applied to reduce/fold operation. Many basic statistical functions could be implemented that way (eg. avg, stddev, sum, min, max). This has been proposed on the Guava issues list, but was regarded as 'too functional'. – Dibbeke Feb 05 '13 at 10:56
  • In this case I'm not - I want a unary function returning void, that accepts T. For example, the typical loop: `for (T elem : iterable) { sink.consume(elem); }` would be replaced by something like `Iterables.apply(iterable, sink)` (or perhaps `Consumables.consume`, etc). – BeeOnRope Feb 05 '13 at 11:33
  • 4
    _In the meantime, Predicate and Function are ugly workarounds._ - for-each loop is elegant solution then (until Java 8). – Grzegorz Rożniecki Feb 05 '13 at 11:44
  • 1
    +1 @Xaerxess. The primary reason Guava doesn't have this is that we don't have compelling use cases: as of Java 7, as far as we can tell, it's generally cleaner to write this sort of code directly, without using an object to encapuslate the callback. – Louis Wasserman Feb 05 '13 at 23:42
  • `RxJava2` has `io.reactivex.functions.Consumer` which works with Java 7 and in particular earlier Android versions – karmakaze Jan 29 '18 at 01:45

3 Answers3

9

Your alternatives are:

In all of these languages, you can use functional interfaces conveniently, so you could also use e.g. Functional Java's Effect.

Otherwise, you better rely on existing language constructs for performing side effects, e.g. the built-in for loop. Java < 8 inflicts tremendous syntactic overhead when using lambdas. See this question and this discussion.

Community
  • 1
  • 1
thSoft
  • 21,755
  • 5
  • 88
  • 103
0

You can use a Function and set the second Argument to java.lang.Void this Function can only return null.

Robert.MD
  • 21
  • 2
-1

You have already found the answer. If you just want to visit, you can use filter with a predicate that always returns true; if you are super defensive you can use any predicate and use an or function with an alwaysTrue in the filter itself; just add the or at the end to avoid shortcircuiting.

The problem is that even though I agree that conceptually Predicate and Consumer are different since a Predicate should be as stateless as possible and not have side effects while a consumer is only about the side effects, in practice the only syntactic difference is that one returns a boolean (that can be ignored) and the other void. If Guava had a Consumer, it would need to either duplicate several of the methods that take a Predicate to also take a Consumer or have Consumer inherit from Predicate.

Luis
  • 1,294
  • 7
  • 9
  • The problem is that the classes that would implement this are named, general purpose classes and to have them implement Predicate-always-returns-true would be confusing. You could equivalently argue that Supplier is useless - you might as well use Function, ignoring the input. – BeeOnRope Feb 05 '13 at 10:03
  • 3
    Note that Iterables.filter() is lazy, so the "Predicate" consumer won't be called until you actually iterate on the resulting Iterable, which is quite ugly and could lead to bugs... You'd need to write something like `Lists.newArrayList(Iterables.filter(iterable, predicateThatIsActuallyAConsumer));`. I'd rather use a for loop, and a project-specific `Consumer` class. – Etienne Neveu Feb 05 '13 at 10:45
  • 5
    -1 because this does not contribute to the question. A predicate has different behavior and a different type. It would misuse the type system and lead to misunderstanding. It's a hack. – Dibbeke Feb 05 '13 at 10:52