You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Efficiently iterate over a MapValue.
Currently, MapValue can be iterated over by using one of the following methods:
MapValue.entrySet(), which allocates a Map.Entry object for every entry.
MapValue.getKeyValueArray(), which makes a defensive copy of the array.
Iterating over MapValue.map() is no better than iterating over MapValue.entrySet().
Efficiently access a value whose entry index is known or can likely be guessed correctly.
A common use case is constructing a Java object from a MapValue whose pack order is likely known.
Currently, there is no way to benefit from this knowledge:
Value get(Map<Value, Value> map, String key) {
// this is O(n) and produces garbage, could be O(1) and no garbage
return map.get(ValueFactory.newString(key));
}
record LargeRecord(String foo, int bar, ...);
var map = mapValue.map();
var large = new LargeRecord(
get(map, "foo").asStringValue().asString(),
get(map, "bar").asIntegerValue().asInt(),
...
);
Proposal:
To achieve the goals described above, I propose to add the following methods to MapValue:
Value getKey(int entryIndex);
Value getValue(int entryIndex);
Results:
Iterating over MapValue produces no garbage:
for (var i = 0; i < mapValue.size(); i++) {
var key = mapValue.getKey(i);
var value = mapValue.getValue(i);
}
Accessing a value whose entry index is known or guessed correctly is O(1) instead of O(n);
Value get(MapValue mapValue, String stringKey, int guessedIndex) {
var key = mapValue.getKey(guessedIndex);
return key.isStringValue() && stringKey.equals(key.asStringValue().asString()) ?
// fast path
mapValue.getValue(guessedIndex) :
// slow path
mapValue.map().get(ValueFactory.newString(key));
}
var large = new LargeRecord(
get(mapValue, "foo", 0).asStringValue().asString(),
get(mapValue, "bar", 1).asIntegerValue().asInt(),
...
);
Alternatives:
The first goal can be partially achieved by overriding method java.util.Map.forEach() in class ImmutableMapValueMap. This is PR #809 .
The second goal can sometimes be achieved by using Unpacker.unpackMapHeader() etc. instead of Unpacker.unpackValue().asMapValue().
If my proposal is approved, I'd be happy to send a PR.
The text was updated successfully, but these errors were encountered:
Goals:
Efficiently iterate over a
MapValue
.Currently,
MapValue
can be iterated over by using one of the following methods:MapValue.entrySet()
, which allocates aMap.Entry
object for every entry.MapValue.getKeyValueArray()
, which makes a defensive copy of the array.Iterating over
MapValue.map()
is no better than iterating overMapValue.entrySet()
.Efficiently access a value whose entry index is known or can likely be guessed correctly.
A common use case is constructing a Java object from a
MapValue
whose pack order is likely known.Currently, there is no way to benefit from this knowledge:
Proposal:
To achieve the goals described above, I propose to add the following methods to
MapValue
:Results:
MapValue
produces no garbage:Alternatives:
The first goal can be partially achieved by overriding method
java.util.Map.forEach()
in classImmutableMapValueMap
. This is PR #809 .The second goal can sometimes be achieved by using
Unpacker.unpackMapHeader()
etc. instead ofUnpacker.unpackValue().asMapValue()
.If my proposal is approved, I'd be happy to send a PR.
The text was updated successfully, but these errors were encountered: