diff --git a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java index 1408419b7..96ae697d0 100644 --- a/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java +++ b/prometheus-metrics-model/src/main/java/io/prometheus/metrics/model/snapshots/Exemplars.java @@ -24,6 +24,10 @@ public class Exemplars implements Iterable { private final List exemplars; private Exemplars(Collection exemplars) { + if (exemplars.isEmpty()) { + this.exemplars = Collections.emptyList(); + return; + } List copy = new ArrayList<>(exemplars.size()); for (Exemplar exemplar : exemplars) { if (exemplar == null) { @@ -41,7 +45,7 @@ private Exemplars(Collection exemplars) { * @param exemplars a copy of the exemplars collection will be created. */ public static Exemplars of(Collection exemplars) { - return new Exemplars(exemplars); + return exemplars.isEmpty() ? EMPTY : new Exemplars(exemplars); } /** @@ -51,7 +55,7 @@ public static Exemplars of(Collection exemplars) { * @param exemplars a copy of the exemplars array will be created. */ public static Exemplars of(Exemplar... exemplars) { - return new Exemplars(Arrays.asList(exemplars)); + return exemplars.length == 0 ? EMPTY : new Exemplars(Arrays.asList(exemplars)); } @Override diff --git a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java index be69e7f16..605326ea7 100644 --- a/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java +++ b/prometheus-metrics-model/src/test/java/io/prometheus/metrics/model/snapshots/ExemplarsTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import java.util.Collections; import java.util.Iterator; import org.junit.jupiter.api.Test; @@ -53,4 +54,22 @@ void testGet() { assertThat(exemplars.getLatest()).isSameAs(newest); } + + @Test + void testEmptyReturnsSingleton() { + // Empty inputs short-circuit to the EMPTY singleton, avoiding allocations. + assertThat(Exemplars.of()).isSameAs(Exemplars.EMPTY); + assertThat(Exemplars.of(Collections.emptyList())).isSameAs(Exemplars.EMPTY); + assertThat(Exemplars.builder().build()).isSameAs(Exemplars.EMPTY); + } + + @Test + void testEmptyIteratorIsSingleton() { + // Collections.emptyList().iterator() returns the JDK singleton empty iterator, so reading an + // empty Exemplars allocates no iterator. + assertThat(Exemplars.EMPTY.size()).isZero(); + assertThat(Exemplars.EMPTY.iterator()).isSameAs(Collections.emptyIterator()); + assertThat(Exemplars.EMPTY.get(0.0, Double.POSITIVE_INFINITY)).isNull(); + assertThat(Exemplars.EMPTY.getLatest()).isNull(); + } }