Skip to content

Commit 548d752

Browse files
CopilotiCrawlalmeidxkodiakhq[bot]
authored
perf: Optimize Collection.equals() to reduce redundant map lookups (#11344)
* Initial plan * Optimize Collection.equals() to avoid redundant map lookups Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com> * Add explanatory comment for equals() undefined check optimization Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: iCrawl <20760160+iCrawl@users.noreply.github.com> Co-authored-by: Almeida <github@almeidx.dev> Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
1 parent 6a129bc commit 548d752

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

packages/collection/__tests__/collection.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,23 @@ describe('equals() tests', () => {
207207
const coll3 = createCollectionFrom(['a', 2], ['b', 3], ['c', 3]);
208208
expect(coll2.equals(coll3)).toBeFalsy();
209209
});
210+
211+
test('collections with undefined values should be compared correctly', () => {
212+
const collWithUndefined1 = new Collection<string, number | undefined>([
213+
['a', 1],
214+
['b', undefined],
215+
]);
216+
const collWithUndefined2 = new Collection<string, number | undefined>([
217+
['a', 1],
218+
['b', undefined],
219+
]);
220+
const collWithDifferentKeys = new Collection<string, number | undefined>([
221+
['a', 1],
222+
['c', undefined],
223+
]);
224+
expect(collWithUndefined1.equals(collWithUndefined2)).toBeTruthy();
225+
expect(collWithUndefined1.equals(collWithDifferentKeys)).toBeFalsy();
226+
});
210227
});
211228

212229
describe('every() tests', () => {

packages/collection/src/collection.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,11 @@ export class Collection<Key, Value> extends Map<Key, Value> {
822822
if (this === collection) return true;
823823
if (this.size !== collection.size) return false;
824824
for (const [key, value] of this) {
825-
if (!collection.has(key) || value !== collection.get(key)) {
825+
const otherValue = collection.get(key);
826+
// If values differ, collections aren't equal.
827+
// For undefined values, we must also verify the key exists in the other collection,
828+
// since get() returns undefined for both missing keys and keys with undefined values.
829+
if (otherValue !== value || (otherValue === undefined && !collection.has(key))) {
826830
return false;
827831
}
828832
}

0 commit comments

Comments
 (0)