Skip to content

Commit

Permalink
dedup keys in Id.unsafeCreate (#975)
Browse files Browse the repository at this point in the history
Since this method is already sorting and that is needed
for finding duplicates, have it do the deduplication as
well. This will add a bit of overhead for existing usage
where it is already known that there are no duplicates.
  • Loading branch information
brharrington authored May 20, 2022
1 parent 1fe89a9 commit 5a0cd38
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ static ArrayTagSet create(Map<String, String> tags) {
* <ul>
* <li>Length of tags array is even.</li>
* <li>There are no null values for the first length entries in the array.</li>
* <li>There are no duplicate tag keys.</li>
* </ul>
*/
static ArrayTagSet unsafeCreate(String[] tags, int length) {
insertionSort(tags, length);
return new ArrayTagSet(tags, length);
int len = dedupInPlace(tags, length);
return new ArrayTagSet(tags, len);
}

private final String[] tags;
Expand Down Expand Up @@ -283,7 +283,7 @@ private static void insertionSort(String[] ts, int length) {
* Merge and dedup any entries in {@code ts} that have the same key. The last entry
* with a given key will get selected.
*/
private int merge(String[] dst, String[] srcA, int lengthA, String[] srcB, int lengthB) {
private static int merge(String[] dst, String[] srcA, int lengthA, String[] srcB, int lengthB) {
int i = 0;
int ai = 0;
int bi = 0;
Expand Down Expand Up @@ -332,7 +332,7 @@ private int merge(String[] dst, String[] srcA, int lengthA, String[] srcB, int l
* key will get selected. Input data must already be sorted by the tag key. Returns the
* length of the overall deduped array.
*/
private int dedup(String[] src, int ss, String[] dst, int ds, int len) {
private static int dedup(String[] src, int ss, String[] dst, int ds, int len) {
if (len == 0) {
return ds;
} else {
Expand All @@ -356,6 +356,34 @@ private int dedup(String[] src, int ss, String[] dst, int ds, int len) {
}
}

/**
* Dedup any entries in {@code data} that have the same key. The last entry with a given
* key will get selected. Input data must already be sorted by the tag key. Returns the
* length of the overall deduped array.
*/
private static int dedupInPlace(String[] data, int len) {
if (len == 0) {
return 0;
} else {
String k = data[0];
int j = 0;
for (int i = 2; i < len; i += 2) {
if (k.equals(data[i])) {
data[j] = data[i];
data[j + 1] = data[i + 1];
} else {
j += 2; // Not deduping, skip over previous entry
k = data[i];
if (i > j) {
data[j] = k;
data[j + 1] = data[i + 1];
}
}
}
return j + 2;
}
}

/** Return the key at the specified position. */
@Override public String getKey(int i) {
return tags[i * 2];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ static Id create(String name) {
* <ul>
* <li>Length of tags array is even.</li>
* <li>There are no null values for the first length entries in the array.</li>
* <li>There are no duplicate tag keys.</li>
* </ul>
*/
static Id unsafeCreate(String name, String[] tags, int length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,11 @@ public void unsafeCreate() {
Id expected = Id.create("foo").withTags("k2", "v2", "k1", "v1");
Assertions.assertEquals(expected, id);
}

@Test
public void unsafeCreateDuplicates() {
Id id = Id.unsafeCreate("foo", new String[] {"k1", "_", "k2", "v2", "k1", "v1", null, null}, 6);
Id expected = Id.create("foo").withTags("k1", "_", "k1", "v1", "k2", "v2");
Assertions.assertEquals(expected, id);
}
}

0 comments on commit 5a0cd38

Please sign in to comment.