Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #33860

Re: stream filter twice

From Sebastian <news@seyweiler.dyndns.org>
Newsgroups comp.lang.java.programmer
Subject Re: stream filter twice
Date 2016-02-22 00:13 +0100
Organization albasani.net
Message-ID <nadgbe$mj$1@news.albasani.net> (permalink)
References <04334e10-3bad-49dc-87d8-dc2f00f90807@googlegroups.com> <nabaej$1rfq$1@gioia.aioe.org> <ditn2rF45nnU1@mid.individual.net>

Show all headers | View raw


Am 21.02.2016 12:58, schrieb Robert Klemme:
> On 21.02.2016 04:20, Arne Vajhøj wrote:
>
>> What is your goal? To produce easily understandable code? To save
>> a few micro seconds?
>
> That is really the first question to answer.
>
>> If the first then I think you current code is fine.
>>
>> If the second then you will need to be creative.
>>
>> Here is my attempt to be creative:
>
> I'm a bit more old fashioned, maybe that's why I do not find the
> advantage of streams so big here.  I was also considering, we might not
> know how large the initial collection is.  So the cost of iterating
> twice could be significant.  So:
[code snipped]

I also assume that iterating twice would lead to unacceptable runtime.

The excellent library jool (https://github.com/jOOQ/jOOL) has what they 
call "combining collectors". These are higher-order collectors that 
apply a number of other collectors simultaneously to a stream and return 
a tuple (in our case a pair) of results.

The collector to be applied would have to be a filtering collector. Java 
8 does not have one, but there will be such a beast in Java 9, see here: 
https://bugs.openjdk.java.net/browse/JDK-8144675

You can use these two elements to get a solution that is very similar to 
Eric's idea of abusing groupingBy:

Collector<T, ?, Tuple2<List<T>, List<T>>> filtering = Tuple.collectors(
     filtering(filter, toList()), filtering(anotherFilter, toList()));
Tuple2<List<T>,List<T>> filtered =  mycoll.stream().collect(filtering);
return !filtered.v1.isEmpty() ? filtered.v1 : filtered.v2;

It shares with Eric's idea the advantages of being parallelizable, which 
would be more difficult with Arne's and Robert's suggestions, and using 
official or well-established libraries.

-- Sebastian


PS: I append the very bare bones of the necessary parts from JDK 9 and 
the jool library (this will work, akthough the original code is a bit 
different, please look at the sources cited above for the real thing).

public static <T, A, R> Collector<T, A, R> filtering(
                               Predicate<? super T> predicate,
                               Collector<? super T, A, R> downstream) {
     return Collector.of(
                 downstream.supplier(),
                 (r, t) -> { if (predicate.test(t)) {
                               downstream.accumulator().accept(r, t);
                            }},
                 downstream.combiner(),
                 downstream.finisher());
}

public static interface Tuple {

     static <T1, T2> Tuple2<T1, T2> tuple(T1 v1, T2 v2) {
         return new Tuple2<>(v1, v2);
     }

     static <T, A1, A2, D1, D2>
         Collector<T, Tuple2<A1, A2>, Tuple2<D1, D2>>
             collectors(Collector<T, A1, D1> collector1,
                        Collector<T, A2, D2> collector2) {
                 return Collector.<T, Tuple2<A1, A2>, Tuple2<D1, D2>> of(
                     () -> tuple(
                         collector1.supplier().get(),
                         collector2.supplier().get()),
                     (a, t) -> {
                         collector1.accumulator().accept(a.v1, t);
                         collector2.accumulator().accept(a.v2, t);
                     } ,
                     (a1, a2) -> tuple(
                         collector1.combiner().apply(a1.v1, a2.v1),
                         collector2.combiner().apply(a1.v2, a2.v2)),
                     a -> tuple(
                         collector1.finisher().apply(a.v1),
                         collector2.finisher().apply(a.v2))
                );
     }
}

public static class Tuple2<T1, T2> implements Tuple {

     public final T1 v1;
     public final T2 v2;

     public Tuple2(T1 v1, T2 v2) {
         this.v1 = v1;
         this.v2 = v2;
     }
}

Back to comp.lang.java.programmer | Previous | Next — Previous in thread | Find similar | Unroll thread


Thread

stream filter twice Philipp Kraus <philipp.kraus.flashpixx@gmail.com> - 2016-02-20 04:28 -0800
  Re: stream filter twice Eric Sosman <esosman@comcast-dot-net.invalid> - 2016-02-20 08:16 -0500
  Re: stream filter twice Arne Vajhøj <arne@vajhoej.dk> - 2016-02-20 22:20 -0500
    Re: stream filter twice Robert Klemme <shortcutter@googlemail.com> - 2016-02-21 12:58 +0100
      Re: stream filter twice Arne Vajhøj <arne@vajhoej.dk> - 2016-02-21 09:52 -0500
      Re: stream filter twice Sebastian <news@seyweiler.dyndns.org> - 2016-02-22 00:13 +0100

csiph-web