The intent is that the collector is free to either call the identity function, or replace it with an unchecked cast instead, and client code cannot tell the difference.

On 10/9/2018 10:48 AM, Chris Dennis wrote:
I’m attempting to clarify the meaning/intent of the language in the 
specification of the identity-finish characteristic of collectors.

The javadoc reads:

     Indicates that the finisher function is the identity function and
     can be elided.  If set, it must be the case that an unchecked cast
     from A to R will succeed.

In the following code the second sentence clearly indicates that the second 
cast from A to R must succeed. What I’m trying to confirm however is that the 
first sentence is intended to require that the finisher is a true identity 
function, so the result of the collector must be one of the instances created 
through the supplier, and that therefore the cast from R to A is also safe.

public static void main(String[] args) {
   Stream<String> a = Stream.of("foo", "bar", "baz");
   Stream<String> b = Stream.of("alice", "bob", "eve");

   System.out.println(collect(Stream.of(a, b), partitioningBy(s -> 
s.startsWith("b"), toList())));
}

public static <T, A, R> R collect(Stream<Stream<T>> streams, Collector<T, A, R> 
collector) {
   if 
(collector.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH))
 {
     return streams.map(s -> s.collect(collector))
         // Indicates that the finisher function is the identity function and 
can be elided.
         .map(r -> (A) r)
         .reduce(collector.combiner())

         // If set, it must be the case that an unchecked cast from A to R will 
succeed.
         .map(a -> (R) a)
         .orElse(Stream.<T>empty().collect(collector));
   } else {
     return streams.flatMap(identity()).collect(collector);
   }
}

Thoughts, opinions?

Thanks,

Chris Dennis

Reply via email to