diff --git a/common/src/main/java/dev/cel/common/internal/AdaptingTypes.java b/common/src/main/java/dev/cel/common/internal/AdaptingTypes.java index 48158bd91..4cfe1ff4a 100644 --- a/common/src/main/java/dev/cel/common/internal/AdaptingTypes.java +++ b/common/src/main/java/dev/cel/common/internal/AdaptingTypes.java @@ -118,7 +118,12 @@ public Iterator iterator() { @Override public Object[] toArray() { - return delegate.stream().map(baseEl -> converter().convert(baseEl)).toArray(); + Object[] result = new Object[size()]; + int i = 0; + for (A a : delegate) { + result[i++] = converter().convert(a); + } + return result; } @Override diff --git a/runtime/src/main/java/dev/cel/runtime/Activation.java b/runtime/src/main/java/dev/cel/runtime/Activation.java index 074a461a2..11328fb1c 100644 --- a/runtime/src/main/java/dev/cel/runtime/Activation.java +++ b/runtime/src/main/java/dev/cel/runtime/Activation.java @@ -109,11 +109,9 @@ public static Activation copyOf(Map map) { final ImmutableMap copy = (map instanceof ImmutableMap) ? (ImmutableMap) map - : map.entrySet().stream() - // ImmutableMaps are null-hostile, but the Activation is not, so make sure that null - // values and entries are skipped. - .filter(entry -> entry.getKey() != null && entry.getValue() != null) - .collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)); + : // ImmutableMaps are null-hostile, but the Activation is not, so make sure that null + // values and entries are skipped. + toImmutableMapFilteringNulls(map); return new Activation() { @Override @@ -128,6 +126,23 @@ public String toString() { }; } + /** + * Creates an {@link ImmutableMap} from the given {@link Map} filtering out null keys and values. + * + *

Used instead of the one-liner for performance reasons. + */ + private static ImmutableMap toImmutableMapFilteringNulls(Map map) { + ImmutableMap.Builder builder = ImmutableMap.builderWithExpectedSize(map.size()); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (key != null && value != null) { + builder.put(key, value); + } + } + return builder.buildOrThrow(); + } + /** * Extends this binder by another binder. Names will be attempted to first resolve in the other * binder, then in this binder. diff --git a/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java b/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java index fa22b1d00..ab268850d 100644 --- a/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java +++ b/runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java @@ -499,7 +499,10 @@ private IntermediateResult dispatchCall( return IntermediateResult.create(attr, unknowns.get()); } - Object[] argArray = Arrays.stream(argResults).map(IntermediateResult::value).toArray(); + Object[] argArray = new Object[argResults.length]; + for (int i = 0; i < argResults.length; i++) { + argArray[i] = argResults[i].value(); + } ImmutableList overloadIds = reference.overloadIds(); CelResolvedOverload overload = findOverloadOrThrow(frame, expr, callExpr.function(), overloadIds, argArray);