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