Trouble with wildcards

Remi Forax forax at univ-mlv.fr
Sat Dec 14 10:43:48 PST 2013


Hi all,
I've tried to explain in code how a Stream (here a Flow to avoid 
confusion) can be implemented (just filter/map, only a sequential 
stream) with consecutive operations, filter.filter or map.map optimized.

I end up with the code below which compiles but if instead of
   return Flow.this.filter(/*predicate.and(predicate2)*/ t -> 
predicate.test(t) && predicate2.test(t));
I replace it by
   return Flow.this.filter(predicate.and(predicate2));
the compiler refuses to compile and I don't understand why :(

Here predicate is a Predicate<? super T>, so predicate2 should be a 
Predicate<? super ? super T>,
because and() is declared like this: Predicate<T>.and(Predicate<? super T>)
predicate2 is a Predicate<? super T> so it should match Predicate<? 
super ? super T> but
it doesn't.

Is it a bug in the compiler or in my head ?

cheers,
Rémi

@FunctionalInterface
public interface Flow<T> {
   public void forEach(Consumer<? super T> consumer);

   public default Flow<T> filter(Predicate<? super T> predicate) {
     return new Flow<T>() {
       @Override
       public void forEach(Consumer<? super T> consumer) {
         Flow.this.forEach(u -> {
           if (predicate.test(u)) {
             consumer.accept(u);
           }
         });
       }
       @Override
       public Flow<T> filter(Predicate<? super T> predicate2) {
         return Flow.this.filter(/*predicate.and(predicate2)*/ t -> 
predicate.test(t) && predicate2.test(t));
       }
     };
   }

   public default <R> Flow<R> map(Function<? super T, ? extends R> 
function) {
     return new Flow<R>() {
       @Override
       public void forEach(Consumer<? super R> consumer) {
         Flow.this.forEach(t -> consumer.accept(function.apply(t)));
       }
       @Override
       public <U> Flow<U> map(Function<? super R, ? extends U> function2) {
         return Flow.this.map(function.andThen(function2));
       }
     };
   }

   public static <T> Flow<T> create(Iterable<? extends T> iterable) {
     return iterable::forEach;
   }

   public static void main(String[] args) {
     List<Integer> list = IntStream.range(0, 
10).boxed().collect(Collectors.toList());
     Flow<Integer> flow = create(list);
     flow.filter(x -> x != 5).filter(x -> x != 
2).forEach(System.out::println);
     flow.map(x -> x * 2).map(x -> x + 1).forEach(System.out::println);
     flow.filter(x -> x != 5).map(x -> x * 2).filter(x -> x != 2).map(x 
-> x / 2).forEach(System.out::println);
   }
}


More information about the lambda-dev mailing list