337 * @param <T> the type of the input elements
338 * @param <U> type of elements accepted by downstream collector
339 * @param <A> intermediate accumulation type of the downstream collector
340 * @param <R> result type of collector
341 * @param mapper a function to be applied to the input elements
342 * @param downstream a collector which will accept mapped values
343 * @return a collector which applies the mapping function to the input
344 * elements and provides the mapped results to the downstream collector
345 */
346 public static <T, U, A, R>
347 Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
348 Collector<? super U, A, R> downstream) {
349 BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
350 return new CollectorImpl<>(downstream.supplier(),
351 (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
352 downstream.combiner(), downstream.finisher(),
353 downstream.characteristics());
354 }
355
356 /**
357 * Returns a {@code Collector} accepting elements of type {@code T} that
358 * counts the number of input elements. If no elements are present, the
359 * result is 0.
360 *
361 * @implSpec
362 * This produces a result equivalent to:
363 * <pre>{@code
364 * reducing(0L, e -> 1L, Long::sum)
365 * }</pre>
366 *
367 * @param <T> the type of the input elements
368 * @return a {@code Collector} that counts the input elements
369 */
370 public static <T> Collector<T, ?, Long>
371 counting() {
372 return reducing(0L, e -> 1L, Long::sum);
373 }
374
375 /**
376 * Returns a {@code Collector} that produces the minimal element according
|
337 * @param <T> the type of the input elements
338 * @param <U> type of elements accepted by downstream collector
339 * @param <A> intermediate accumulation type of the downstream collector
340 * @param <R> result type of collector
341 * @param mapper a function to be applied to the input elements
342 * @param downstream a collector which will accept mapped values
343 * @return a collector which applies the mapping function to the input
344 * elements and provides the mapped results to the downstream collector
345 */
346 public static <T, U, A, R>
347 Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
348 Collector<? super U, A, R> downstream) {
349 BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
350 return new CollectorImpl<>(downstream.supplier(),
351 (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
352 downstream.combiner(), downstream.finisher(),
353 downstream.characteristics());
354 }
355
356 /**
357 * Adapts a {@code Collector} to perform an additional finishing
358 * transformation. For example, one could adapt the {@link #toList()}
359 * collector to always produce an immutable list with:
360 * <pre>{@code
361 * List<String> people
362 * = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
363 * }</pre>
364 *
365 * @param <T> the type of the input elements
366 * @param <A> intermediate accumulation type of the downstream collector
367 * @param <R> result type of the downstream collector
368 * @param <RR> result type of the resulting collector
369 * @param downstream a collector
370 * @param finisher a function to be applied to the final result of the downstream collector
371 * @return a collector which performs the action of the downstream collector,
372 * followed by an additional finishing step
373 */
374 public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
375 Function<R,RR> finisher) {
376 Set<Collector.Characteristics> characteristics = downstream.characteristics();
377 if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
378 if (characteristics.size() == 1)
379 characteristics = Collectors.CH_NOID;
380 else {
381 characteristics = EnumSet.copyOf(characteristics);
382 characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
383 characteristics = Collections.unmodifiableSet(characteristics);
384 }
385 }
386 return new CollectorImpl<>(downstream.supplier(),
387 downstream.accumulator(),
388 downstream.combiner(),
389 downstream.finisher().andThen(finisher),
390 characteristics);
391 }
392
393 /**
394 * Returns a {@code Collector} accepting elements of type {@code T} that
395 * counts the number of input elements. If no elements are present, the
396 * result is 0.
397 *
398 * @implSpec
399 * This produces a result equivalent to:
400 * <pre>{@code
401 * reducing(0L, e -> 1L, Long::sum)
402 * }</pre>
403 *
404 * @param <T> the type of the input elements
405 * @return a {@code Collector} that counts the input elements
406 */
407 public static <T> Collector<T, ?, Long>
408 counting() {
409 return reducing(0L, e -> 1L, Long::sum);
410 }
411
412 /**
413 * Returns a {@code Collector} that produces the minimal element according
|