Stream Method Proposal: long count(Predicate<? super T> predicate)

Brian Goetz brian.goetz at
Tue Nov 13 14:47:57 UTC 2018

Exactly right.

Note, though, that count() is _already_ a convenience method!  You could call .collect(counting()) instead.  So, why were we willing to add count() and similar methods, when we’re not willing to add this one?  Several reasons:

 - Discoverability.  Collect() is complicated, and until you understand the whole API (and the power of collect()) a new user would be stymied by how to do something simple like count or sum a list.  So sometimes, discoverability is a good reason to violate the preference against gratuitous convenience methods.

 - Performance.  For a large class of stream sources, there’s an optimization for counting that turns it into an O(1) operation (ask the spliterator if it knows its size), which collect() can’t do.  So sometimes, turning an O(n) operation into an O(1) operation is a good enough reason to violate the preference against gratuitous convenience methods.  

There are others too, but this one doesn’t clear the bar.  

> On Nov 12, 2018, at 12:50 AM, James Roper <james at> wrote:
> Another reason to prefer a smaller API is that it can aid the ability to
> comprehend, since there's less concepts to understand. The idea behind
> design patterns is that APIs constrain themselves to just using the well
> established and understood patterns, which means when someone who has never
> seen the API before comes and sees code that uses it, they can understand
> the code. But that only works if APIs do constrain themselves to the design
> patterns - constraint is key to the advantageous application of design
> patterns to APIs. does not sit by itself, it is one of
> hundreds of APIs on the JVM alone, including other languages it's among
> thousands of APIs that offer a functional API with filter and count
> abstractions. All of these APIs share filter/count as well established,
> well understood, instantly readable and understandable concepts. You don't
> have to know anything about to be able to understand
> exactly what filter(predicate).count() is doing. And this bootstrapping off
> this large ecosystem of APIs is one of the things that make
> a good API. But if it were to add count/findFirst variants
> that add predicates? It's not unprecedented, but it is by far less common,
> which makes it less understandable. That doesn't mean we never add
> convenience methods, but they do have to add a high degree of convenience
> to diverge from the well established patterns, and in this case, the
> convenience added is only small.
> On Fri, 9 Nov 2018 at 04:39, Roger Riggs <Roger.Riggs at> wrote:
>> Hi Jacob,
>> Its hard to resist the urge to add convenience methods, they look nice
>> and help a few developers.
>> However, they accumulate rapidly and end up obscuring the core
>> functionality.
>> They can hurt comprehension since they fold different functions together
>> and the collective API surface area ends up impinging on every
>> developers learning curve.
>> $.02, Roger
>> On 11/07/2018 08:00 PM, Jacob Glickman wrote:
>>>  Hello!
>>> I see myself having to often call count() as a terminal operation on a
>>> Stream immediately after performing a filter operation. How feasible
>> would
>>> it be to add an overloaded count() method that accepts a Predicate, which
>>> it uses as a filter before returning the count of elements in the Stream?
>>> If this is supported, I'd gladly create the webrev & tests for it!
>>> I suppose the method signature can be something along the lines of:
>>>     long count(Predicate<? super T> predicate)
>>> It would also seem reasonable to give this method to IntStream,
>>> DoubleStream, and LongStream, but allowing them to use IntPredicate,
>>> DoublePredicate, and LongPredicate respectively.
>>> Thanks,
>>> Jacob Glickman
> -- 
> James Roper
> Architect, Office of the CTO, Lightbend, Inc.
> @jroper <>
> <>

More information about the core-libs-dev mailing list