diff --git a/components/context/src/main/java/datadog/context/IndexedContext.java b/components/context/src/main/java/datadog/context/IndexedContext.java index e2c520fffdb..18d6448b3d3 100644 --- a/components/context/src/main/java/datadog/context/IndexedContext.java +++ b/components/context/src/main/java/datadog/context/IndexedContext.java @@ -30,6 +30,9 @@ public T get(ContextKey key) { public Context with(ContextKey key, @Nullable T value) { requireNonNull(key, "Context key cannot be null"); int index = key.index; + if (index < this.store.length && this.store[index] == value) { + return this; + } Object[] newStore = copyOfRange(this.store, 0, max(this.store.length, index + 1)); newStore[index] = value; return new IndexedContext(newStore); diff --git a/components/context/src/main/java/datadog/context/SingletonContext.java b/components/context/src/main/java/datadog/context/SingletonContext.java index 94c9ff091fc..34d05cf72fd 100644 --- a/components/context/src/main/java/datadog/context/SingletonContext.java +++ b/components/context/src/main/java/datadog/context/SingletonContext.java @@ -31,9 +31,13 @@ public Context with(ContextKey secondKey, @Nullable V secondValue) { requireNonNull(secondKey, "Context key cannot be null"); int secondIndex = secondKey.index; if (this.index == secondIndex) { - return secondValue == null - ? EmptyContext.INSTANCE - : new SingletonContext(this.index, secondValue); + if (secondValue == null) { + return EmptyContext.INSTANCE; + } else if (secondValue != this.value) { + return new SingletonContext(this.index, secondValue); + } else { + return this; + } } else { Object[] store = new Object[max(this.index, secondIndex) + 1]; store[this.index] = this.value; diff --git a/components/context/src/test/java/datadog/context/ContextTest.java b/components/context/src/test/java/datadog/context/ContextTest.java index 8bf69b645cb..ceb76b11b39 100644 --- a/components/context/src/test/java/datadog/context/ContextTest.java +++ b/components/context/src/test/java/datadog/context/ContextTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -165,6 +166,17 @@ void testToString(Context context) { "Context string representation should contain implementation name"); } + @ParameterizedTest + @MethodSource("contextImplementations") + void testWithSameValueReturnsThis(Context context) { + String value = "value"; + Context context1 = context.with(STRING_KEY, value); + // storing the same value again should return the same instance + assertSame(context1, context1.with(STRING_KEY, value)); + // storing a different value should return a new instance + assertNotEquals(context1, context1.with(STRING_KEY, "other")); + } + @SuppressWarnings({"SimplifiableAssertion"}) @Test void testInflation() {