Optimize MultiValueMap iteration operations

* use forEach and putIfAbsent to copy headers in DefaultClientRequestBuilder
* use forEach in ReactorClientHttpRequest and ReactorNetty2ClientHttpRequest
* circumvent ReadOnlyHttpHeaders.entrySet()
* ensure the fast path to LinkedCaseInsensitiveMap for forEach and putIfAbsent exists

Closes gh-29972
This commit is contained in:
James Yuzawa
2023-02-14 20:26:52 -05:00
committed by Brian Clozel
parent beb23b5da6
commit 5dacf50b9b
9 changed files with 88 additions and 22 deletions

View File

@@ -40,6 +40,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -1821,6 +1822,16 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
return this.headers.entrySet();
}
@Override
public void forEach(BiConsumer<? super String, ? super List<String>> action) {
this.headers.forEach(action);
}
@Override
public List<String> putIfAbsent(String key, List<String> value) {
return this.headers.putIfAbsent(key, value);
}
@Override
public boolean equals(@Nullable Object obj) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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.
@@ -23,6 +23,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import org.springframework.lang.Nullable;
@@ -155,4 +156,9 @@ class ReadOnlyHttpHeaders extends HttpHeaders {
Collections::unmodifiableSet));
}
@Override
public void forEach(BiConsumer<? super String, ? super List<String>> action) {
this.headers.forEach((k, vs) -> action.accept(k, Collections.unmodifiableList(vs)));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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,7 +18,6 @@ package org.springframework.http.client.reactive;
import java.net.URI;
import java.nio.file.Path;
import java.util.Collection;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.cookie.DefaultCookie;
@@ -129,9 +128,10 @@ class ReactorClientHttpRequest extends AbstractClientHttpRequest implements Zero
@Override
protected void applyCookies() {
getCookies().values().stream().flatMap(Collection::stream)
.map(cookie -> new DefaultCookie(cookie.getName(), cookie.getValue()))
.forEach(this.request::addCookie);
getCookies().values().forEach(values -> values.forEach(value -> {
DefaultCookie cookie = new DefaultCookie(value.getName(), value.getValue());
this.request.addCookie(cookie);
}));
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 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,7 +18,6 @@ package org.springframework.http.client.reactive;
import java.net.URI;
import java.nio.file.Path;
import java.util.Collection;
import io.netty5.buffer.Buffer;
import io.netty5.handler.codec.http.headers.DefaultHttpCookiePair;
@@ -130,9 +129,10 @@ class ReactorNetty2ClientHttpRequest extends AbstractClientHttpRequest implement
@Override
protected void applyCookies() {
getCookies().values().stream().flatMap(Collection::stream)
.map(cookie -> new DefaultHttpCookiePair(cookie.getName(), cookie.getValue()))
.forEach(this.request::addCookie);
getCookies().values().forEach(values -> values.forEach(value -> {
DefaultHttpCookiePair cookie = new DefaultHttpCookiePair(value.getName(), value.getValue());
this.request.addCookie(cookie);
}));
}
@Override