HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

A Java subclass of ArrayList that supports rotation in constant time

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
constantsupportsjavarotationtimesubclassthatarraylist

Problem

(See the next iteration.)

I have subclassed java.util.ArrayList in order to be able to "rotate" it in constant time simply by moving a finger index. See what I have:

RotableList.java

```
package net.coderodde.util;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.Spliterator;

/**
* This class implements a rotable list. Pushing to the front or the end of this
* list runs in constant amortized time. Rotation runs in constant time.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Mar 24, 2016)
*/
public class RotableList extends ArrayList {

private int finger;

@Override
public E get(int index) {
checkAccessIndex(index);
return super.get((index + finger) % size());
}

@Override
public E set(int index, E element) {
checkAccessIndex(index);
E ret = get(index);
super.set((index + finger) % size(), element);
return ret;
}

@Override
public void add(int index, E element) {
checkAdditionIndex(index);
super.add((index + finger) % (size() + 1), element);
}

@Override
public boolean add(E element) {
add(size(), element);
return true;
}

@Override
public E remove(int index) {
checkRemovalIndex(index);
E ret = get(index);
super.remove((index + finger) % size());
return ret;
}

@Override
public int indexOf(Object o) {
int size = size();

for (int index = 0; index = 0; --index) {
if (Objects.equals(o, get(index))) {
return index;
}
}

return -1;
}

@Override
public void sort(Comparator c) {
super.sort(c);
finger = 0;
}

@Override
public Iterator iterator() {
throw new UnsupportedOperationException();
}

@Override
public ListI

Solution

Your code does not throw UnsupportedOperationException for addAll, when you don't guarantee the index of the ordering. The contract of ArrayList.addAll is as such:


Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's Iterator.

Your code violates this contract, as the elements are inserted at the wrong position.

Test case:

RotableList list = new RotableList<>();
list.add(5);
list.add(1);
list.add(2);
list.add(3);
list.add(4);

ArrayList list2 = new ArrayList<>();
list2.add(6);
list2.add(7);
list2.add(8);

list.rotate(-1);
System.out.println(list);

list.addAll(list2);
System.out.println(list);

RotableList list3 = new RotableList<>();
list3.add(1);
list3.add(2);
list3.add(3);
list3.add(4);
list3.add(5);

ArrayList list4 = new ArrayList<>();
list4.add(6);
list4.add(7);
list4.add(8);

list3.addAll(list4);
System.out.println(list3);


Result:

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 6, 7, 8, 5]
[1, 2, 3, 4, 5, 6, 7, 8]


You also don't reset the finger in clear, leading to funky business with other operations such as retainAll and removeAll.

Code Snippets

RotableList<Integer> list = new RotableList<>();
list.add(5);
list.add(1);
list.add(2);
list.add(3);
list.add(4);

ArrayList<Integer> list2 = new ArrayList<>();
list2.add(6);
list2.add(7);
list2.add(8);

list.rotate(-1);
System.out.println(list);

list.addAll(list2);
System.out.println(list);

RotableList<Integer> list3 = new RotableList<>();
list3.add(1);
list3.add(2);
list3.add(3);
list3.add(4);
list3.add(5);

ArrayList<Integer> list4 = new ArrayList<>();
list4.add(6);
list4.add(7);
list4.add(8);

list3.addAll(list4);
System.out.println(list3);
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 6, 7, 8, 5]
[1, 2, 3, 4, 5, 6, 7, 8]

Context

StackExchange Code Review Q#123736, answer score: 7

Revisions (0)

No revisions yet.