From b790bd1fd6843129c706139861914a0405dc86a3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 11 Jun 2018 14:10:12 +0200 Subject: [PATCH] LinkedCaseInsensitiveMap explicitly implements put/computeIfAbsent Issue: SPR-16926 --- .../util/LinkedCaseInsensitiveMap.java | 31 +++++++++++++++-- .../util/LinkedCaseInsensitiveMapTests.java | 34 +++++++++---------- 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java b/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java index ab243f4f5f..844b92f600 100644 --- a/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java +++ b/spring-core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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.LinkedHashMap; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.function.Function; import org.springframework.lang.Nullable; @@ -151,6 +152,7 @@ public class LinkedCaseInsensitiveMap implements Map, Serializable } @Override + @Nullable public V getOrDefault(Object key, V defaultValue) { if (key instanceof String) { String caseInsensitiveKey = this.caseInsensitiveKeys.get(convertKey((String) key)); @@ -162,12 +164,15 @@ public class LinkedCaseInsensitiveMap implements Map, Serializable } @Override + @Nullable public V put(String key, @Nullable V value) { String oldKey = this.caseInsensitiveKeys.put(convertKey(key), key); + V oldKeyValue = null; if (oldKey != null && !oldKey.equals(key)) { - this.targetMap.remove(oldKey); + oldKeyValue = this.targetMap.remove(oldKey); } - return this.targetMap.put(key, value); + V oldValue = this.targetMap.put(key, value); + return (oldKeyValue != null ? oldKeyValue : oldValue); } @Override @@ -178,6 +183,26 @@ public class LinkedCaseInsensitiveMap implements Map, Serializable map.forEach(this::put); } + @Override + @Nullable + public V putIfAbsent(String key, @Nullable V value) { + String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key); + if (oldKey != null) { + return this.targetMap.get(oldKey); + } + return this.targetMap.putIfAbsent(key, value); + } + + @Override + @Nullable + public V computeIfAbsent(String key, Function mappingFunction) { + String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key); + if (oldKey != null) { + return this.targetMap.get(oldKey); + } + return this.targetMap.computeIfAbsent(key, mappingFunction); + } + @Override @Nullable public V remove(Object key) { diff --git a/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java b/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java index ae0fd141be..a9f8dcfd88 100644 --- a/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java +++ b/spring-core/src/test/java/org/springframework/util/LinkedCaseInsensitiveMapTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2018 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. @@ -30,9 +30,9 @@ public class LinkedCaseInsensitiveMapTests { @Test public void putAndGet() { - map.put("key", "value1"); - map.put("key", "value2"); - map.put("key", "value3"); + assertNull(map.put("key", "value1")); + assertEquals("value1", map.put("key", "value2")); + assertEquals("value2", map.put("key", "value3")); assertEquals(1, map.size()); assertEquals("value3", map.get("key")); assertEquals("value3", map.get("KEY")); @@ -47,9 +47,9 @@ public class LinkedCaseInsensitiveMapTests { @Test public void putWithOverlappingKeys() { - map.put("key", "value1"); - map.put("KEY", "value2"); - map.put("Key", "value3"); + assertNull(map.put("key", "value1")); + assertEquals("value1", map.put("KEY", "value2")); + assertEquals("value2", map.put("Key", "value3")); assertEquals(1, map.size()); assertEquals("value3", map.get("key")); assertEquals("value3", map.get("KEY")); @@ -64,9 +64,9 @@ public class LinkedCaseInsensitiveMapTests { @Test public void getOrDefault() { - map.put("key", "value1"); - map.put("KEY", "value2"); - map.put("Key", "value3"); + assertNull(map.put("key", "value1")); + assertEquals("value1", map.put("KEY", "value2")); + assertEquals("value2", map.put("Key", "value3")); assertEquals("value3", map.getOrDefault("key", "N")); assertEquals("value3", map.getOrDefault("KEY", "N")); assertEquals("value3", map.getOrDefault("Key", "N")); @@ -76,9 +76,9 @@ public class LinkedCaseInsensitiveMapTests { @Test public void getOrDefaultWithNullValue() { - map.put("key", null); - map.put("KEY", null); - map.put("Key", null); + assertNull(map.put("key", null)); + assertNull(map.put("KEY", null)); + assertNull(map.put("Key", null)); assertNull(map.getOrDefault("key", "N")); assertNull(map.getOrDefault("KEY", "N")); assertNull(map.getOrDefault("Key", "N")); @@ -88,9 +88,9 @@ public class LinkedCaseInsensitiveMapTests { @Test public void computeIfAbsentWithExistingValue() { - map.put("key", "value1"); - map.put("KEY", "value2"); - map.put("Key", "value3"); + assertNull(map.putIfAbsent("key", "value1")); + assertEquals("value1", map.putIfAbsent("KEY", "value2")); + assertEquals("value1", map.put("Key", "value3")); assertEquals("value3", map.computeIfAbsent("key", key -> "value1")); assertEquals("value3", map.computeIfAbsent("KEY", key -> "value2")); assertEquals("value3", map.computeIfAbsent("Key", key -> "value3")); @@ -105,7 +105,7 @@ public class LinkedCaseInsensitiveMapTests { @Test public void mapClone() { - map.put("key", "value1"); + assertNull(map.put("key", "value1")); LinkedCaseInsensitiveMap copy = map.clone(); assertEquals(map.getLocale(), copy.getLocale());