51

I have a need in a block of code to consume 'n' items from a stream then finish, in essence:

 public static <T> void eat(Stream<T> stream, int n) 
     // consume n items of the stream (and throw them away)
 }

In my situation, I can't change the signature to return Stream<T> and simply return stream.skip(n); I have to actually throw away some elements from the stream (not simple logic) - to be ready for a down stream consumer which doesn't need to know how, or even that, this has happened.

The simplest way to do this is to use limit(n), but I have to call a stream terminating method to activate the stream, so in essence I have:

public static <T> void skip(Stream<T> stream, int n) {
    stream.limit(n).forEach(t -> {});
}

Note: This code is a gross over simplification of the actual code and is for illustrative purposes only. Actually, limit won't work because there is logic around what/how to consume elements. Think of it like consuming "header" elements from a stream, then having a consumer consume the "body" elements.

This question is about the "do nothing" lambda t -> {}.

Is there a "do nothing" consumer somewhere in the JDK, like the "do nothing" function Function.identity()?

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 11
    The do-nothing Consumer is indeed `t -> { }` and we've decided not to add more named functions like `Function.identity()`. See http://stackoverflow.com/a/26553481/1441122 and http://www.lambdafaq.org/are-there-other-constant-lambdas-like-function-identity/ . – Stuart Marks Feb 10 '16 at 04:49
  • 7
    Possible XY problem? The only way `limit(n).forEach(t -> { })` could be significant is if there are side effects upstream. Side effects aren't forbidden *per se* but it makes one wonder what you're really trying to do. – Stuart Marks Feb 10 '16 at 04:54
  • 3
    @StuartMarks, plus one. While op says the original code is oversimplified, it still looks highly suspicious. I rarely use empty consumer in `assertFalse(spliterator.tryAdvance(t -> {}))`, though even here it would be better to `assertFalse(spliterator.tryAdvance(t -> fail("Should not be called")))`. – Tagir Valeev Feb 10 '16 at 05:40
  • 5
    why does the caller need this method if it can just do `stream.skip(n)` – ZhongYu Feb 10 '16 at 05:48
  • @bayou.io I told you this is a gross over simplification and not to focus on the actual code. In fact, there is no `n` parameter and the caller doesn't know how to consume `n` elements anyway, because it doesn't know what to skip or filter etc. The situation is a pre-process of a stream to bring it to a point where another downstream consumer can start its work. I've edited the question to provide more context. – Bohemian Feb 10 '16 at 17:51
  • @Bohemian - I didn't pay attention who asked the question. Usually you just presume that the guy didn't know what he's doing:) But you of course know what you are doing. – ZhongYu Feb 10 '16 at 18:10
  • 1
    @bayou.io: are you sure? After all, this kind of preprocessing doesn’t work at all, as `forEach` is a terminal operation, and the idea of bringing a stream into a certain state is far off the entire idea of how streams work. – Holger Feb 10 '16 at 18:42
  • It's not possible to implement `eat(Stream stream, int n)` the way you (Bohemian) want because any implementation would have to operate on that stream. Any subsequent operation on the stream by the caller would result in an exception, since the stream has been "consumed," even if no terminal operation has been added. If you want to do something like this, you need to find a way to get the caller to use a new stream in place of the old one. – Stuart Marks Feb 10 '16 at 19:21
  • 1
    It sounds like you want something like `dropWhile()` in JDK 9. Presumably you need to stick with JDK 8, though, so you could pursue some approach like `skip()`, a stateful `filter()`, or getting an `Iterator` from the stream, pulling the first few elements, and then creating a new stream from it using `StreamSupport`. I'm sure **StreamEx** has something that can help. But in all cases you need to pass a new stream back to the caller to use in place of the old one. – Stuart Marks Feb 10 '16 at 19:25
  • @Holger -- I've learned that our imagination never covers all possible use cases. Maybe OP wants to move a cursor at the data source, and he chooses to use a short circuiting Stream to bring that effect; and another consumer will start a new Stream, from the new cursor position. – ZhongYu Feb 10 '16 at 20:49
  • @bayou.io: so when creating a stream from that source you’ll play lottery regarding at which cursor position the previous stream operation has left it? That’s what I call being far off the original spirit… – Holger Feb 10 '16 at 21:15
  • @Holger -- well, that is just imperative, stateful programming :) and I believe OP knows how to control and protect the states. – ZhongYu Feb 10 '16 at 22:11
  • 1
    @Bohemian, considering the interest arose around this question, could you possibly ask another question like "is there better way to do it?", providing more details to your original problem like what is the stream source, why you need to modify it in this way and what do you want to do later with the modified source? – Tagir Valeev Feb 11 '16 at 01:51

3 Answers3

53

No, JDK does not provide dummy consumer as well as other predefined functions like dummy runnable, always-true predicate or supplier which always returns zero. Just write t -> {}, it's anyways shorter than calling any possible ready method which will do the same.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • 5
    Now *you* I believe (having created StreamEx). I ask not because it's shorter, faster etc, but because using a named "do nothing" method, such as "identity()", declares intention (and definitely not an empty placeholder for a "do something" implementation) – Bohemian Feb 10 '16 at 05:35
  • 5
    @Bohemian: nobody stops you from defining a `static final Consumer DO_NOTHING=x->{};` constant and using it throughout your application. But the bigger question is why you think you need that. [As said](http://stackoverflow.com/questions/35306760/does-the-jdk-provide-a-dummy-consumer#comment58324055_35306760), it’s a big code smell and very likely that there is a cleaner solution without a no-op `Consumer`. – Holger Feb 10 '16 at 09:04
  • 1
    @Holger that is exactly what I would do, but I was checking to see if I was reinventing a wheel. See [my comment above](http://stackoverflow.com/questions/35306760/does-the-jdk-provide-a-dummy-consumer#comment58353526_35306760) for a bit more context. I was trying to keep the code in the Q as simple and narrowly relevant as possible. The situation is some elements (relatively complex logic) need to be thrown away from the head of the stream, but how that should be done is kept within the method. I've edited the Q to add more context. – Bohemian Feb 10 '16 at 17:55
  • 2
    unfortunately (the implementation of) the simple lambda is not as context-independent as it looks; in this [case](http://stackoverflow.com/questions/34820066), `Function.identity()` is better than `i->i` – ZhongYu Feb 10 '16 at 18:08
  • 3
    @Bohemian: that still makes no sense at all. `forEach` is a terminal operation which makes the entire stream unusable. You can't “throw away from the head of the stream” this way. In other words, if you want to skip elements, use `Stream.skip`, nothing else. There's still no valid use case for `forEach(NO_OP)` – Holger Feb 10 '16 at 18:18
  • You want a valid usecase? Consider a scenario where you need to log a warning/info notice based on the state of an `Optional`, _e.g._ using `ifPresentOrElse(..)`. – Priidu Neemre Mar 15 '21 at 12:51
5

Introducing the dummy (empty) consumer was considered in the scope of the ticket:

According to the ticket, it was decided not to introduce it.

Therefore, there is no dummy (empty) consumer in the JDK.

4

Yes. Well, more or less yes...

Since a Function is also a Consumer, you can use Function.identity() as a "do nothing" Consumer.

However, the compiler needs a little help to make the leap:

someStream.forEach(identity()::apply);
Bohemian
  • 412,405
  • 93
  • 575
  • 722