Skip to content

Commit

Permalink
Add KTypeArrayList removeAt and rename remove to removeElement.
Browse files Browse the repository at this point in the history
Optimize removal methods to only dereference removed elements when the list is generic.
  • Loading branch information
bruno-roustant committed May 24, 2024
1 parent 6a2913d commit 012bde5
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 58 deletions.
44 changes: 33 additions & 11 deletions hppc/src/main/templates/com/carrotsearch/hppc/KTypeArrayList.java
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,28 @@ public KType set(int index, KType e1) {
* {@inheritDoc}
*/
@Override
public KType remove(int index) {
public KType removeAt(int index) {
assert (index >= 0 && index < size()) : "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";

final KType v = Intrinsics.<KType> cast(buffer[index]);
if (index + 1 < elementsCount) {
System.arraycopy(buffer, index + 1, buffer, index, elementsCount - index - 1);
}
elementsCount--;
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
/* #if ($TemplateOptions.KTypeGeneric) */
buffer[elementsCount] = Intrinsics.empty();
/* #end */
return v;
}

/**
* {@inheritDoc}
*/
@Override
public KType removeLast() {
assert elementsCount > 0;

final KType v = Intrinsics.<KType> cast(buffer[--elementsCount]);
/* #if ($TemplateOptions.KTypeGeneric) */
buffer[elementsCount] = Intrinsics.empty();
/* #end */
return v;
}

Expand All @@ -245,7 +258,17 @@ public void removeRange(int fromIndex, int toIndex) {
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
final int count = toIndex - fromIndex;
elementsCount -= count;
/* #if ($TemplateOptions.KTypeGeneric) */
Arrays.fill(buffer, elementsCount, elementsCount + count, Intrinsics.empty());
/* #end */
}

/**
* {@inheritDoc}
*/
@Override
public boolean removeElement(KType e1) {
return removeFirst(e1) != -1;
}

/**
Expand All @@ -255,7 +278,7 @@ public void removeRange(int fromIndex, int toIndex) {
public int removeFirst(KType e1) {
final int index = indexOf(e1);
if (index >= 0)
remove(index);
removeAt(index);
return index;
}

Expand All @@ -266,7 +289,7 @@ public int removeFirst(KType e1) {
public int removeLast(KType e1) {
final int index = lastIndexOf(e1);
if (index >= 0)
remove(index);
removeAt(index);
return index;
}

Expand All @@ -278,19 +301,18 @@ public int removeAll(KType e1) {
int to = 0;
for (int from = 0; from < elementsCount; from++) {
if (Intrinsics.equals(this, e1, buffer[from])) {
buffer[from] = Intrinsics.empty();
continue;
}

if (to != from) {
buffer[to] = buffer[from];
buffer[from] = Intrinsics.empty();
}
to++;
}

final int deleted = elementsCount - to;
this.elementsCount = to;
/* #if ($TemplateOptions.KTypeGeneric) */
Arrays.fill(buffer, elementsCount, elementsCount + deleted, Intrinsics.empty());
/* #end */
return deleted;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
*/
/*! ${TemplateOptions.generatedAnnotation} !*/
public interface KTypeIndexedContainer<KType> extends KTypeCollection<KType>, RandomAccess {
/**
* Removes the first element that equals <code>e1</code>, returning whether
* an element has been removed.
*/
public boolean removeElement(KType e1);

/**
* Removes the first element that equals <code>e1</code>, returning its
* deleted position or <code>-1</code> if the element was not found.
Expand Down Expand Up @@ -68,7 +74,13 @@ public interface KTypeIndexedContainer<KType> extends KTypeCollection<KType>, Ra
* @see #removeLast
* @see #removeAll
*/
public KType remove(int index);
public KType removeAt(int index);

/**
* Removes and returns the last element of this container.
* This container must not be empty.
*/
public KType removeLast();

/**
* Removes from this container all of the elements with indexes between
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,7 @@ public void discard() {
* Remove the top element from the stack and return it.
*/
public KType pop() {
assert elementsCount > 0;

final KType v = Intrinsics.<KType> cast(buffer[--elementsCount]);
/* #if ($TemplateOptions.KTypeGeneric) */
buffer[elementsCount] = null;
/* #end */
return v;
return removeLast();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public void initialize()
list = new KTypeArrayList<>();
}

/*! #if ($TemplateOptions.KTypeGeneric) !*/
@After
public void checkTrailingSpaceUninitialized()
{
Expand All @@ -43,6 +44,7 @@ public void checkTrailingSpaceUninitialized()
assertTrue(Intrinsics.<KType> empty() == list.buffer[i]);
}
}
/*! #end !*/

/* */
@Test
Expand Down Expand Up @@ -125,17 +127,34 @@ public void testSet()

/* */
@Test
public void testRemove()
public void testRemoveAt()
{
list.add(asArray(0, 1, 2, 3, 4));

list.remove(0);
list.remove(2);
list.remove(1);
list.removeAt(0);
list.removeAt(2);
list.removeAt(1);

assertListEquals(list.toArray(), 1, 4);
}

/* */
@Test
public void testRemoveLast() {
list.add(asArray(0, 1, 2, 3, 4));

assertEquals2(4, list.removeLast());
assertEquals2(4, list.size());
assertListEquals(list.toArray(), 0, 1, 2, 3);
assertEquals2(3, list.removeLast());
assertEquals2(3, list.size());
assertListEquals(list.toArray(), 0, 1, 2);
assertEquals2(2, list.removeLast());
assertEquals2(1, list.removeLast());
assertEquals2(0, list.removeLast());
assertTrue(list.isEmpty());
}

/* */
@Test
public void testRemoveRange()
Expand Down Expand Up @@ -173,17 +192,16 @@ public void testRemoveFirstLast()
assertListEquals(list.toArray(), 2, 1);
assertEquals(-1, list.removeLast(k0));

/*! #if ($TemplateOptions.KTypeGeneric) !*/
list.clear();
list.add(newArray(k0, null, k2, null, k0));
assertEquals(1, list.removeFirst(null));
assertEquals(2, list.removeLast(null));
assertListEquals(list.toArray(), 0, 2, 0);
/*! #end !*/
list.add(newArray(k1, Intrinsics.empty(), k2, Intrinsics.empty(), k1));
assertEquals(1, list.removeFirst(Intrinsics.empty()));
assertEquals(2, list.removeLast(Intrinsics.empty()));
assertListEquals(list.toArray(), 1, 2, 1);
}

/* */
@Test
@SuppressWarnings("unchecked")
public void testRemoveAll()
{
list.add(asArray(0, 1, 0, 1, 0));
Expand All @@ -195,13 +213,11 @@ public void testRemoveAll()
assertEquals(2, list.removeAll(k1));
assertTrue(list.isEmpty());

/*! #if ($TemplateOptions.KTypeGeneric) !*/
list.clear();
list.add(newArray(k0, null, k2, null, k0));
assertEquals(2, list.removeAll((KType) null));
assertEquals(0, list.removeAll((KType) null));
assertListEquals(list.toArray(), 0, 2, 0);
/*! #end !*/
list.add(newArray(k1, Intrinsics.empty(), k2, Intrinsics.empty(), k1));
assertEquals(2, list.removeAll((KType) Intrinsics.empty()));
assertEquals(0, list.removeAll((KType) Intrinsics.empty()));
assertListEquals(list.toArray(), 1, 2, 1);
}

/*! #if (not $TemplateOptions.isKTypeAnyOf("DOUBLE", "FLOAT", "BYTE")) !*/
Expand Down Expand Up @@ -286,33 +302,31 @@ public boolean apply(KType v)

/* */
@Test
@SuppressWarnings("unchecked")
public void testIndexOf()
{
list.add(asArray(0, 1, 2, 1, 0));
list.add(asArray(3, 1, 2, 1, 3));

/*! #if ($TemplateOptions.KTypeGeneric) !*/
list.add((KType) null);
assertEquals(5, list.indexOf(null));
/*! #end !*/
list.add((KType) Intrinsics.empty());
assertEquals(5, list.indexOf(Intrinsics.empty()));

assertEquals(0, list.indexOf(k0));
assertEquals(-1, list.indexOf(k3));
assertEquals(0, list.indexOf(k3));
assertEquals(-1, list.indexOf(k4));
assertEquals(2, list.indexOf(k2));
}

/* */
@Test
@SuppressWarnings("unchecked")
public void testLastIndexOf()
{
list.add(asArray(0, 1, 2, 1, 0));
list.add(asArray(3, 1, 2, 1, 3));

/*! #if ($TemplateOptions.KTypeGeneric) !*/
list.add((KType) null);
assertEquals(5, list.lastIndexOf(null));
/*! #end !*/
list.add((KType) Intrinsics.empty());
assertEquals(5, list.lastIndexOf(Intrinsics.empty()));

assertEquals2(4, list.lastIndexOf(k0));
assertEquals2(-1, list.lastIndexOf(k3));
assertEquals2(4, list.lastIndexOf(k3));
assertEquals2(-1, list.lastIndexOf(k4));
assertEquals2(2, list.lastIndexOf(k2));
}

Expand Down Expand Up @@ -485,7 +499,8 @@ public void testClear()
{
list.add(asArray( 1, 2, 3));
list.clear();
checkTrailingSpaceUninitialized();
assertTrue(list.isEmpty());
assertEquals(-1, list.indexOf(cast(1)));
}

/* */
Expand Down Expand Up @@ -525,17 +540,15 @@ public void testEqualElements()
assertTrue(l2.equalElements(l1));
}

/*! #if ($TemplateOptions.KTypeGeneric) !*/
@Test
public void testHashCodeWithNulls()
public void testHashCodeWithEmptyKeys()
{
KTypeArrayList<KType> l1 = KTypeArrayList.from(k1, null, k3);
KTypeArrayList<KType> l2 = KTypeArrayList.from(k1, null, k3);
KTypeArrayList<KType> l1 = KTypeArrayList.from(k1, Intrinsics.empty(), k3);
KTypeArrayList<KType> l2 = KTypeArrayList.from(k1, Intrinsics.empty(), k3);

assertEquals(l1.hashCode(), l2.hashCode());
assertEquals(l1, l2);
}
/*! #end !*/

/*! #if ($TemplateOptions.KTypeGeneric) !*/
@Test
Expand All @@ -547,10 +560,10 @@ class A {
class B extends A {
}

KTypeArrayList<B> list2 = new KTypeArrayList<B>();
KTypeArrayList<B> list2 = new KTypeArrayList<>();
list2.add(new B());

KTypeArrayList<A> list3 = new KTypeArrayList<A>();
KTypeArrayList<A> list3 = new KTypeArrayList<>();
list3.add(new B());
list3.add(new A());
list3.addAll(list2);
Expand Down

0 comments on commit 012bde5

Please sign in to comment.