From 96ee102e198fbac5b55a3d1d9fa09fd28b2e8910 Mon Sep 17 00:00:00 2001 From: Tobias Ibounig Date: Fri, 12 Jun 2026 11:53:35 +0200 Subject: [PATCH] perf: skip iterating over empty list Signed-off-by: Tobias Ibounig --- .../java/dev/openfeature/sdk/HookSupport.java | 3 ++ .../dev/openfeature/sdk/HookSupportTest.java | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/main/java/dev/openfeature/sdk/HookSupport.java b/src/main/java/dev/openfeature/sdk/HookSupport.java index e936fdeda..0891134b3 100644 --- a/src/main/java/dev/openfeature/sdk/HookSupport.java +++ b/src/main/java/dev/openfeature/sdk/HookSupport.java @@ -45,6 +45,9 @@ public void setHooks( private static void addFilteredHooks( List> dest, Collection source, FlagValueType type) { + if (source.isEmpty()) { + return; + } for (Hook hook : source) { if (hook.supportsFlagValueType(type)) { dest.add(Pair.of(hook, null)); diff --git a/src/test/java/dev/openfeature/sdk/HookSupportTest.java b/src/test/java/dev/openfeature/sdk/HookSupportTest.java index f7583321a..8d60122d3 100644 --- a/src/test/java/dev/openfeature/sdk/HookSupportTest.java +++ b/src/test/java/dev/openfeature/sdk/HookSupportTest.java @@ -14,6 +14,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentLinkedQueue; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -161,6 +162,37 @@ void shouldOrderHooksBySource() { .containsExactly(providerHook, optionHook, clientHook, apiHook); } + @Test + @DisplayName("empty ConcurrentLinkedQueue sources produce no hooks") + void emptyQueueSourcesProduceNoHooks() { + var hookSupportData = new HookSupportData(); + hookSupport.setHooks( + hookSupportData, + new ConcurrentLinkedQueue<>(), + new ConcurrentLinkedQueue<>(), + new ConcurrentLinkedQueue<>(), + new ConcurrentLinkedQueue<>(), + FlagValueType.STRING); + assertThat(hookSupportData.getHooks()).isEmpty(); + } + + @Test + @DisplayName("non-empty ConcurrentLinkedQueue source is not skipped") + void nonEmptyQueueSourceIsNotSkipped() { + Hook hook = mockGenericHook(); + var queue = new ConcurrentLinkedQueue(); + queue.add(hook); + var hookSupportData = new HookSupportData(); + hookSupport.setHooks( + hookSupportData, + new ConcurrentLinkedQueue<>(), + new ConcurrentLinkedQueue<>(), + queue, + new ConcurrentLinkedQueue<>(), + FlagValueType.STRING); + assertThat(hookSupportData.getHooks()).extracting(Pair::getKey).containsExactly(hook); + } + @Test void hookThatReturnsTheGivenContext_doesNotResultInAStackOverflow() { var hookSupportData = new HookSupportData();