Skip to content

Commit 3e37402

Browse files
alanpaxtonadamretter
authored andcommitted
[refactor] merge duplicates: combine, reject
Reject by counting expected size of merge. Combine uses a merge-with-combine fn from the underlying collection code. Passes an initial set of tests. There’s some code we have written for completeness (MapType merge with combiner operator) which doesn’t seem to get called. Need to investigate/test further.
1 parent 0bd3df6 commit 3e37402

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

exist-core/src/main/java/org/exist/xquery/functions/map/AbstractMapType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,4 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
241241
return map.get((AtomicValue) args[0].itemAt(0));
242242
}
243243
}
244-
}
244+
}

exist-core/src/main/java/org/exist/xquery/functions/map/MapType.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,43 @@ public AbstractMapType merge(final Iterable<AbstractMapType> others, final Binar
247247
return new MapType(context, newMap.forked(), prevType);
248248
}
249249

250+
@Override
251+
public AbstractMapType merge(final Iterable<AbstractMapType> others, final BinaryOperator<Sequence> mergeFn) {
252+
253+
// create a transient map
254+
IMap<AtomicValue, Sequence> newMap = map.linear();
255+
256+
int prevType = keyType;
257+
for (final AbstractMapType other: others) {
258+
if (other instanceof MapType) {
259+
// MapType - optimise merge
260+
final MapType otherMap = (MapType) other;
261+
newMap = newMap.merge(otherMap.map, mergeFn);
262+
263+
if (prevType != otherMap.keyType) {
264+
prevType = MIXED_KEY_TYPES;
265+
}
266+
} else {
267+
// non MapType
268+
for (final IEntry<AtomicValue, Sequence> entry : other) {
269+
final AtomicValue key = entry.key();
270+
final Optional<Sequence> headEntry = newMap.get(key);
271+
if (headEntry.isPresent()) {
272+
newMap = newMap.put(key, mergeFn.apply(headEntry.get(), entry.value()));
273+
} else {
274+
newMap = newMap.put(key, entry.value());
275+
}
276+
if (prevType != key.getType()) {
277+
prevType = MIXED_KEY_TYPES;
278+
}
279+
}
280+
}
281+
}
282+
283+
// return an immutable map
284+
return new MapType(context, newMap.forked(), prevType);
285+
}
286+
250287
public void add(final AtomicValue key, final Sequence value) {
251288
setKeyType(key.getType());
252289
map = map.put(key, value);

exist-core/src/main/java/org/exist/xquery/functions/map/SingleKeyMapType.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ public AbstractMapType merge(final Iterable<AbstractMapType> others, final Binar
8787
}
8888
}
8989

90+
@Override
91+
public AbstractMapType merge(final Iterable<AbstractMapType> others, final BinaryOperator<Sequence> mergeFn) {
92+
final MapType map = new MapType(context, collator, key, value);
93+
return map.merge(others, mergeFn);
94+
}
95+
9096
@Override
9197
public AbstractMapType put(final AtomicValue key, final Sequence value) {
9298
final IMap<AtomicValue, Sequence> map = newLinearMap(collator);

0 commit comments

Comments
 (0)