From 0a0299693bc7d3dad05ca4c8fcb2c3459ca2e131 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Wed, 4 Nov 2020 14:19:58 +0100 Subject: [PATCH] Do not create intermediate list in MergedAnnotationCollectors.toAnnotationSet() Prior to this commit, MergedAnnotationCollectors.toAnnotationSet() created an intermediate ArrayList for storing the results prior to creating a LinkedHashSet in the finishing step. Since the creation of the intermediate list is unnecessary, this commit simplifies the implementation of toAnnotationSet() by using the Collector.of() factory method that does not accept a `finisher` argument. The resulting Collector internally uses a `castingIdentity()` function as the `finisher`. Closes gh-26031 --- .../MergedAnnotationCollectors.java | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java index 4efb5cb606..d09369f916 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/MergedAnnotationCollectors.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,8 @@ package org.springframework.core.annotation; import java.lang.annotation.Annotation; import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashSet; -import java.util.List; import java.util.Set; import java.util.function.Function; import java.util.function.IntFunction; @@ -31,10 +31,11 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; /** - * Collector implementations that provide various reduction operations for + * {@link Collector} implementations that provide various reduction operations for * {@link MergedAnnotation} instances. * * @author Phillip Webb + * @author Sam Brannen * @since 5.2 */ public abstract class MergedAnnotationCollectors { @@ -52,13 +53,16 @@ public abstract class MergedAnnotationCollectors { * Create a new {@link Collector} that accumulates merged annotations to a * {@link LinkedHashSet} containing {@linkplain MergedAnnotation#synthesize() * synthesized} versions. + *

The collector returned by this method is effectively equivalent to + * {@code Collectors.mapping(MergedAnnotation::synthesize, Collectors.toCollection(LinkedHashSet::new))} + * but avoids the creation of a composite collector. * @param the annotation type * @return a {@link Collector} which collects and synthesizes the * annotations into a {@link Set} */ public static Collector, ?, Set> toAnnotationSet() { - return Collector.of(ArrayList::new, (list, annotation) -> list.add(annotation.synthesize()), - MergedAnnotationCollectors::addAll, LinkedHashSet::new); + return Collector.of(LinkedHashSet::new, (set, annotation) -> set.add(annotation.synthesize()), + MergedAnnotationCollectors::combiner); } /** @@ -90,14 +94,14 @@ public abstract class MergedAnnotationCollectors { IntFunction generator) { return Collector.of(ArrayList::new, (list, annotation) -> list.add(annotation.synthesize()), - MergedAnnotationCollectors::addAll, list -> list.toArray(generator.apply(list.size()))); + MergedAnnotationCollectors::combiner, list -> list.toArray(generator.apply(list.size()))); } /** - * Create a new {@link Collector} that accumulates merged annotations to an + * Create a new {@link Collector} that accumulates merged annotations to a * {@link MultiValueMap} with items {@linkplain MultiValueMap#add(Object, Object) * added} from each merged annotation - * {@link MergedAnnotation#asMap(Adapt...) as a map}. + * {@linkplain MergedAnnotation#asMap(Adapt...) as a map}. * @param the annotation type * @param adaptations the adaptations that should be applied to the annotation values * @return a {@link Collector} which collects and synthesizes the @@ -111,13 +115,13 @@ public abstract class MergedAnnotationCollectors { } /** - * Create a new {@link Collector} that accumulates merged annotations to an + * Create a new {@link Collector} that accumulates merged annotations to a * {@link MultiValueMap} with items {@linkplain MultiValueMap#add(Object, Object) * added} from each merged annotation - * {@link MergedAnnotation#asMap(Adapt...) as a map}. + * {@linkplain MergedAnnotation#asMap(Adapt...) as a map}. * @param the annotation type - * @param adaptations the adaptations that should be applied to the annotation values * @param finisher the finisher function for the new {@link MultiValueMap} + * @param adaptations the adaptations that should be applied to the annotation values * @return a {@link Collector} which collects and synthesizes the * annotations into a {@link LinkedMultiValueMap} * @see #toMultiValueMap(MergedAnnotation.Adapt...) @@ -130,7 +134,7 @@ public abstract class MergedAnnotationCollectors { IDENTITY_FINISH_CHARACTERISTICS : NO_CHARACTERISTICS); return Collector.of(LinkedMultiValueMap::new, (map, annotation) -> annotation.asMap(adaptations).forEach(map::add), - MergedAnnotationCollectors::merge, finisher, characteristics); + MergedAnnotationCollectors::combiner, finisher, characteristics); } @@ -138,13 +142,22 @@ public abstract class MergedAnnotationCollectors { return instance == candidate; } - private static > L addAll(L list, L additions) { - list.addAll(additions); - return list; + /** + * {@link Collector#combiner() Combiner} for collections. + *

This method is only invoked if the {@link java.util.stream.Stream} is + * processed in {@linkplain java.util.stream.Stream#parallel() parallel}. + */ + private static > C combiner(C collection, C additions) { + collection.addAll(additions); + return collection; } - private static MultiValueMap merge(MultiValueMap map, - MultiValueMap additions) { + /** + * {@link Collector#combiner() Combiner} for multi-value maps. + *

This method is only invoked if the {@link java.util.stream.Stream} is + * processed in {@linkplain java.util.stream.Stream#parallel() parallel}. + */ + private static MultiValueMap combiner(MultiValueMap map, MultiValueMap additions) { map.addAll(additions); return map; }