Optimize some iterations in BodyExtractor and BodyInserter

This commit turns some stream-based iterations back into simpler
enhanced for loops.

For simple use cases like these, where the stream API is merely used to
map/filter + collect to a List, a for loop is more efficient.
This is especially true for small collections like the ones we deal
with in BodyInserters/BodyExtractors here (in the order of 50ns/op vs
5ns/op). These cases are also simple enough that they don't lose in
readability after the conversion.

Closes gh-30136
This commit is contained in:
James Yuzawa 2023-03-22 06:04:54 -04:00 committed by GitHub
parent 4e896c8125
commit 800b13492b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 32 deletions

View File

@ -147,8 +147,10 @@ public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
this.commitActions.add(writeAction);
}
List<? extends Publisher<Void>> actions = this.commitActions.stream()
.map(Supplier::get).toList();
List<Publisher<Void>> actions = new ArrayList<>(this.commitActions.size());
for (Supplier<? extends Publisher<Void>> commitAction : this.commitActions) {
actions.add(commitAction.get());
}
return Flux.concat(actions).then();
}

View File

@ -194,18 +194,16 @@ public abstract class BodyExtractors {
MediaType contentType = Optional.ofNullable(message.getHeaders().getContentType())
.orElse(MediaType.APPLICATION_OCTET_STREAM);
return context.messageReaders().stream()
.filter(reader -> reader.canRead(elementType, contentType))
.findFirst()
.map(BodyExtractors::<T>cast)
.map(readerFunction)
.orElseGet(() -> {
List<MediaType> mediaTypes = context.messageReaders().stream()
.flatMap(reader -> reader.getReadableMediaTypes(elementType).stream())
.toList();
return errorFunction.apply(
new UnsupportedMediaTypeException(contentType, mediaTypes, elementType));
});
for (HttpMessageReader<?> messageReader : context.messageReaders()) {
if (messageReader.canRead(elementType, contentType)) {
return readerFunction.apply(cast(messageReader));
}
}
List<MediaType> mediaTypes = context.messageReaders().stream()
.flatMap(reader -> reader.getReadableMediaTypes(elementType).stream())
.toList();
return errorFunction.apply(
new UnsupportedMediaTypeException(contentType, mediaTypes, elementType));
}
private static <T> Mono<T> readToMono(ReactiveHttpInputMessage message, BodyExtractor.Context context,
@ -245,12 +243,13 @@ public abstract class BodyExtractors {
private static <T> HttpMessageReader<T> findReader(
ResolvableType elementType, MediaType mediaType, BodyExtractor.Context context) {
return context.messageReaders().stream()
.filter(messageReader -> messageReader.canRead(elementType, mediaType))
.findFirst()
.map(BodyExtractors::<T>cast)
.orElseThrow(() -> new IllegalStateException(
"No HttpMessageReader for \"" + mediaType + "\" and \"" + elementType + "\""));
for (HttpMessageReader<?> messageReader : context.messageReaders()) {
if (messageReader.canRead(elementType, mediaType)) {
return cast(messageReader);
}
}
throw new IllegalStateException(
"No HttpMessageReader for \"" + mediaType + "\" and \"" + elementType + "\"");
}
@SuppressWarnings("unchecked")

View File

@ -373,12 +373,13 @@ public abstract class BodyInserters {
publisher = Mono.just(body);
}
MediaType mediaType = outputMessage.getHeaders().getContentType();
return context.messageWriters().stream()
.filter(messageWriter -> messageWriter.canWrite(bodyType, mediaType))
.findFirst()
.map(BodyInserters::cast)
.map(writer -> write(publisher, bodyType, mediaType, outputMessage, context, writer))
.orElseGet(() -> Mono.error(unsupportedError(bodyType, context, mediaType)));
for (HttpMessageWriter<?> messageWriter : context.messageWriters()) {
if (messageWriter.canWrite(bodyType, mediaType)) {
HttpMessageWriter<Object> typedMessageWriter = cast(messageWriter);
return write(publisher, bodyType, mediaType, outputMessage, context, typedMessageWriter);
}
}
return Mono.error(unsupportedError(bodyType, context, mediaType));
}
private static UnsupportedMediaTypeException unsupportedError(ResolvableType bodyType,
@ -406,12 +407,13 @@ public abstract class BodyInserters {
private static <T> HttpMessageWriter<T> findWriter(
BodyInserter.Context context, ResolvableType elementType, @Nullable MediaType mediaType) {
return context.messageWriters().stream()
.filter(messageWriter -> messageWriter.canWrite(elementType, mediaType))
.findFirst()
.map(BodyInserters::<T>cast)
.orElseThrow(() -> new IllegalStateException(
"No HttpMessageWriter for \"" + mediaType + "\" and \"" + elementType + "\""));
for (HttpMessageWriter<?> messageWriter : context.messageWriters()) {
if (messageWriter.canWrite(elementType, mediaType)) {
return cast(messageWriter);
}
}
throw new IllegalStateException(
"No HttpMessageWriter for \"" + mediaType + "\" and \"" + elementType + "\"");
}
@SuppressWarnings("unchecked")