Commit 5f12b065 by aquilescanta Committed by Oliver Woodman

Support removal of ranges from ShuffleOrders

This allows more efficient range removals and is consistent with addition,
which supports adding multiple elements in a single operation.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=222396310
parent 265462bc
......@@ -570,9 +570,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
if (fromIndex == 0 && toIndex == shuffleOrder.getLength()) {
shuffleOrder = shuffleOrder.cloneAndClear();
} else {
for (int index = toIndex - 1; index >= fromIndex; index--) {
shuffleOrder = shuffleOrder.cloneAndRemove(index);
}
shuffleOrder = shuffleOrder.cloneAndRemove(fromIndex, toIndex);
}
for (int index = toIndex - 1; index >= fromIndex; index--) {
removeMediaSourceInternal(index);
......@@ -581,7 +579,7 @@ public class ConcatenatingMediaSource extends CompositeMediaSource<MediaSourceHo
break;
case MSG_MOVE:
MessageData<Integer> moveMessage = (MessageData<Integer>) Util.castNonNull(message);
shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index);
shuffleOrder = shuffleOrder.cloneAndRemove(moveMessage.index, moveMessage.index + 1);
shuffleOrder = shuffleOrder.cloneAndInsert(moveMessage.customData, 1);
moveMediaSourceInternal(moveMessage.index, moveMessage.customData);
scheduleListenerNotification(moveMessage.actionOnCompletion);
......
......@@ -135,15 +135,16 @@ public interface ShuffleOrder {
}
@Override
public ShuffleOrder cloneAndRemove(int removalIndex) {
int[] newShuffled = new int[shuffled.length - 1];
boolean foundRemovedElement = false;
public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) {
int numberOfElementsToRemove = indexToExclusive - indexFrom;
int[] newShuffled = new int[shuffled.length - numberOfElementsToRemove];
int foundElementsCount = 0;
for (int i = 0; i < shuffled.length; i++) {
if (shuffled[i] == removalIndex) {
foundRemovedElement = true;
if (shuffled[i] >= indexFrom && shuffled[i] < indexToExclusive) {
foundElementsCount++;
} else {
newShuffled[foundRemovedElement ? i - 1 : i] = shuffled[i] > removalIndex
? shuffled[i] - 1 : shuffled[i];
newShuffled[i - foundElementsCount] =
shuffled[i] >= indexFrom ? shuffled[i] - numberOfElementsToRemove : shuffled[i];
}
}
return new DefaultShuffleOrder(newShuffled, new Random(random.nextLong()));
......@@ -213,8 +214,8 @@ public interface ShuffleOrder {
}
@Override
public ShuffleOrder cloneAndRemove(int removalIndex) {
return new UnshuffledShuffleOrder(length - 1);
public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) {
return new UnshuffledShuffleOrder(length - indexToExclusive + indexFrom);
}
@Override
......@@ -268,12 +269,14 @@ public interface ShuffleOrder {
ShuffleOrder cloneAndInsert(int insertionIndex, int insertionCount);
/**
* Returns a copy of the shuffle order with one element removed.
* Returns a copy of the shuffle order with a range of elements removed.
*
* @param removalIndex The index of the element in the unshuffled order which is to be removed.
* @return A copy of this {@link ShuffleOrder} without the removed element.
* @param indexFrom The starting index in the unshuffled order of the range to remove.
* @param indexToExclusive The smallest index (must be greater or equal to {@code indexFrom}) that
* will not be removed.
* @return A copy of this {@link ShuffleOrder} without the elements in the removed range.
*/
ShuffleOrder cloneAndRemove(int removalIndex);
ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive);
/** Returns a copy of the shuffle order with all elements removed. */
ShuffleOrder cloneAndClear();
......
......@@ -45,10 +45,32 @@ public final class ShuffleOrderTest {
testCloneAndInsert(new DefaultShuffleOrder(initialLength, RANDOM_SEED), insertionPoint, 5);
}
}
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4);
testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 0, 1);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 2, 3);
testCloneAndRemove(new DefaultShuffleOrder(5, RANDOM_SEED), 4, 5);
testCloneAndRemove(new DefaultShuffleOrder(1, RANDOM_SEED), 0, 1);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 1000);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 999);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 0, 500);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 100, 600);
testCloneAndRemove(new DefaultShuffleOrder(1000, RANDOM_SEED), 500, 1000);
}
@Test
public void testDefaultShuffleOrderSideloaded() {
int[] shuffledIndices = new int[] {2, 1, 0, 4, 3};
ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED);
assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2);
assertThat(shuffleOrder.getLastIndex()).isEqualTo(3);
for (int i = 0; i < 4; i++) {
assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]);
}
assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET);
for (int i = 4; i > 0; i--) {
assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i]))
.isEqualTo(shuffledIndices[i - 1]);
}
assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET);
}
@Test
......@@ -63,10 +85,15 @@ public final class ShuffleOrderTest {
testCloneAndInsert(new UnshuffledShuffleOrder(initialLength), insertionPoint, 5);
}
}
testCloneAndRemove(new UnshuffledShuffleOrder(5), 0);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 2);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 4);
testCloneAndRemove(new UnshuffledShuffleOrder(1), 0);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 0, 1);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 2, 3);
testCloneAndRemove(new UnshuffledShuffleOrder(5), 4, 5);
testCloneAndRemove(new UnshuffledShuffleOrder(1), 0, 1);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 1000);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 999);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 0, 500);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 100, 600);
testCloneAndRemove(new UnshuffledShuffleOrder(1000), 500, 1000);
}
@Test
......@@ -79,23 +106,6 @@ public final class ShuffleOrderTest {
}
}
@Test
public void testSideloadedShuffleOrder() {
int[] shuffledIndices = new int[] {2, 1, 0, 4, 3};
ShuffleOrder shuffleOrder = new DefaultShuffleOrder(shuffledIndices, RANDOM_SEED);
assertThat(shuffleOrder.getFirstIndex()).isEqualTo(2);
assertThat(shuffleOrder.getLastIndex()).isEqualTo(3);
for (int i = 0; i < 4; i++) {
assertThat(shuffleOrder.getNextIndex(shuffledIndices[i])).isEqualTo(shuffledIndices[i + 1]);
}
assertThat(shuffleOrder.getNextIndex(3)).isEqualTo(C.INDEX_UNSET);
for (int i = 4; i > 0; i--) {
assertThat(shuffleOrder.getPreviousIndex(shuffledIndices[i]))
.isEqualTo(shuffledIndices[i - 1]);
}
assertThat(shuffleOrder.getPreviousIndex(2)).isEqualTo(C.INDEX_UNSET);
}
private static void assertShuffleOrderCorrectness(ShuffleOrder shuffleOrder, int length) {
assertThat(shuffleOrder.getLength()).isEqualTo(length);
if (length == 0) {
......@@ -137,22 +147,24 @@ public final class ShuffleOrderTest {
}
}
private static void testCloneAndRemove(ShuffleOrder shuffleOrder, int position) {
ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(position);
assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - 1);
private static void testCloneAndRemove(
ShuffleOrder shuffleOrder, int indexFrom, int indexToExclusive) {
int numberOfElementsToRemove = indexToExclusive - indexFrom;
ShuffleOrder newOrder = shuffleOrder.cloneAndRemove(indexFrom, indexToExclusive);
assertShuffleOrderCorrectness(newOrder, shuffleOrder.getLength() - numberOfElementsToRemove);
// Assert all elements still have the relative same order
for (int i = 0; i < shuffleOrder.getLength(); i++) {
if (i == position) {
if (i >= indexFrom && i < indexToExclusive) {
continue;
}
int expectedNextIndex = shuffleOrder.getNextIndex(i);
if (expectedNextIndex == position) {
while (expectedNextIndex >= indexFrom && expectedNextIndex < indexToExclusive) {
expectedNextIndex = shuffleOrder.getNextIndex(expectedNextIndex);
}
if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= position) {
expectedNextIndex--;
if (expectedNextIndex != C.INDEX_UNSET && expectedNextIndex >= indexFrom) {
expectedNextIndex -= numberOfElementsToRemove;
}
int newNextIndex = newOrder.getNextIndex(i < position ? i : i - 1);
int newNextIndex = newOrder.getNextIndex(i < indexFrom ? i : i - numberOfElementsToRemove);
assertThat(newNextIndex).isEqualTo(expectedNextIndex);
}
}
......
......@@ -61,8 +61,8 @@ public final class FakeShuffleOrder implements ShuffleOrder {
}
@Override
public ShuffleOrder cloneAndRemove(int removalIndex) {
return new FakeShuffleOrder(length - 1);
public ShuffleOrder cloneAndRemove(int indexFrom, int indexToExclusive) {
return new FakeShuffleOrder(length - indexToExclusive + indexFrom);
}
@Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment