3030import java .util .LinkedList ;
3131import java .util .List ;
3232import java .util .Map ;
33+ import java .util .Objects ;
3334import java .util .Set ;
35+ import java .util .function .BiFunction ;
3436
3537/**
3638 * HTTP request and response headers are represented by this class which
6365 * value given overwriting any existing values in the value list.
6466 * </ul>
6567 *
66- * <p> All methods in this class accept {@code null} values for keys and values.
67- * However, {@code null} keys will never will be present in HTTP request
68- * headers, and will not be output/sent in response headers. Null values can be
69- * represented as either a {@code null} entry for the key (i.e. the list is
70- * {@code null}) or where the key has a list, but one (or more) of the list's
71- * values is {@code null}. Null values are output as a header line containing
72- * the key but no associated value.
73- *
68+ * <p> All methods in this class reject {@code null} values for keys and values.
69+ * {@code null} keys will never be present in HTTP request or response headers.
7470 * @since 1.6
7571 */
7672public class Headers implements Map <String ,List <String >> {
@@ -88,9 +84,7 @@ public class Headers implements Map<String,List<String>> {
8884 * key is presumed to be {@code ASCII}.
8985 */
9086 private String normalize (String key ) {
91- if (key == null ) {
92- return null ;
93- }
87+ Objects .requireNonNull (key );
9488 int len = key .length ();
9589 if (len == 0 ) {
9690 return key ;
@@ -110,54 +104,58 @@ private String normalize(String key) {
110104 return new String (b );
111105 }
112106
107+ @ Override
113108 public int size () {return map .size ();}
114109
110+ @ Override
115111 public boolean isEmpty () {return map .isEmpty ();}
116112
113+ @ Override
117114 public boolean containsKey (Object key ) {
118- if (key == null ) {
119- return false ;
120- }
121- if (!(key instanceof String )) {
122- return false ;
123- }
124- return map .containsKey (normalize ((String )key ));
115+ Objects .requireNonNull (key );
116+ return key instanceof String k && map .containsKey (normalize (k ));
125117 }
126118
119+ @ Override
127120 public boolean containsValue (Object value ) {
121+ Objects .requireNonNull (value );
128122 return map .containsValue (value );
129123 }
130124
125+ @ Override
131126 public List <String > get (Object key ) {
132127 return map .get (normalize ((String )key ));
133128 }
134129
135130 /**
136- * Returns the first value from the {@link List} of {@code String}
137- * values for the given key (if at least one exists).
131+ * Returns the first value from the {@link List} of {@code String} values
132+ * for the given {@code key}, or {@code null} if no mapping for the
133+ * {@code key} exists.
138134 *
139135 * @param key the key to search for
140- * @return the first {@code String} value associated with the key
136+ * @return the first {@code String} value associated with the key,
137+ * or {@code null} if no mapping for the key exists
141138 */
142139 public String getFirst (String key ) {
143140 List <String > l = map .get (normalize (key ));
144- if (l == null ) {
141+ if (l == null || l . size () == 0 ) { // no mapping exists
145142 return null ;
146143 }
147144 return l .get (0 );
148145 }
149146
147+ @ Override
150148 public List <String > put (String key , List <String > value ) {
151149 for (String v : value )
152150 checkValue (v );
153151 return map .put (normalize (key ), value );
154152 }
155153
156154 /**
157- * Adds the given value to the list of headers for the given key. If
158- * the mapping does not already exist, then it is created.
155+ * Adds the given {@code value} to the list of headers for the given
156+ * {@code key}. If the mapping does not already exist, then it is created.
159157 *
160- * @param key the header name
158+ * @param key the header name
161159 * @param value the value to add to the header
162160 */
163161 public void add (String key , String value ) {
@@ -196,10 +194,10 @@ private static void checkValue(String value) {
196194 }
197195
198196 /**
199- * Sets the given value as the sole header value for the given
200- * key. If the mapping does not already exist, then it is created.
197+ * Sets the given {@code value} as the sole header value for the given
198+ * {@code key} . If the mapping does not already exist, then it is created.
201199 *
202- * @param key the header name
200+ * @param key the header name
203201 * @param value the header value to set
204202 */
205203 public void set (String key , String value ) {
@@ -208,25 +206,52 @@ public void set(String key, String value) {
208206 put (key , l );
209207 }
210208
209+ @ Override
211210 public List <String > remove (Object key ) {
212211 return map .remove (normalize ((String )key ));
213212 }
214213
214+ @ Override
215215 public void putAll (Map <? extends String ,? extends List <String >> t ) {
216- map . putAll ( t );
216+ t . forEach ( this :: put );
217217 }
218218
219+ @ Override
219220 public void clear () {map .clear ();}
220221
222+ @ Override
221223 public Set <String > keySet () {return map .keySet ();}
222224
225+ @ Override
223226 public Collection <List <String >> values () {return map .values ();}
224227
228+ @ Override
225229 public Set <Map .Entry <String , List <String >>> entrySet () {
226230 return map .entrySet ();
227231 }
228232
229- public boolean equals (Object o ) {return map .equals (o );}
233+ @ Override
234+ public void replaceAll (BiFunction <? super String , ? super List <String >, ? extends List <String >> function ) {
235+ var f = function .andThen (values -> {
236+ Objects .requireNonNull (values );
237+ values .forEach (Headers ::checkValue );
238+ return values ;
239+ });
240+ Map .super .replaceAll (f );
241+ }
242+
243+ @ Override
244+ public boolean equals (Object o ) { return map .equals (o ); }
230245
246+ @ Override
231247 public int hashCode () {return map .hashCode ();}
248+
249+ @ Override
250+ public String toString () {
251+ final var sb = new StringBuilder (Headers .class .getSimpleName ());
252+ sb .append (" { " );
253+ sb .append (map .toString ());
254+ sb .append (" }" );
255+ return sb .toString ();
256+ }
232257}
0 commit comments