patternjavaMinorCanonical
Implementation of a list-like array
Viewed 0 times
arrayimplementationlistlike
Problem
This is a follow up question for this question:
Implementation of a dynamic list-like array
This is an implementation of an array that behaves like a list, granting me an easy and quick way to:
After following user rolfl answer I revised my class to this
```
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.stream.IntStream;
public class BucketArray implements Iterable {
private final T[] mItems;
private final int[] mSlots;
private int mSlotsTop = -1;
public final int size;
private int mIteratedIndex = -1;
@SuppressWarnings("unchecked")
public BucketArray(Class cast, int size) {
this.size = size;
mItems = (T[]) Array.newInstance(cast, size);
mSlots = IntStream.range(0, size).toArray();
mSlotsTop = size - 1;
}
public int add(T item) {
if (item == null)
return -1;
if (mSlotsTop = size)
throw new IndexOutOfBoundsException();
return mItems[i];
}
public int getIteratedIndex() {
return mIteratedIndex;
}
public boolean remove(int i) {
if (i size)
return false;
if (mItems[i] == null)
return false;
mItems[i] = null;
pushSlot(i);
return true;
}
public void remove(T item) {
remove(indexOf(item));
}
public boolean removeIterated() {
return remove(mIteratedIndex);
}
public boolean isFull() {
return mSlotsTop == -1;
}
public boolean isEmpty() {
return mSlotsTop == size - 1;
}
public int numFreeSlots() {
return mSlotsTop + 1;
}
public int indexOf(T item) {
for (int i = 0; i iterator() {
return new Iterator() {
private int index = -1;
{
if (mIteratedIndex != -1)
Implementation of a dynamic list-like array
This is an implementation of an array that behaves like a list, granting me an easy and quick way to:
- quickly add items
- iterate over them without caring for empty spots in the array
- quickly remove iterated items
After following user rolfl answer I revised my class to this
```
import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.stream.IntStream;
public class BucketArray implements Iterable {
private final T[] mItems;
private final int[] mSlots;
private int mSlotsTop = -1;
public final int size;
private int mIteratedIndex = -1;
@SuppressWarnings("unchecked")
public BucketArray(Class cast, int size) {
this.size = size;
mItems = (T[]) Array.newInstance(cast, size);
mSlots = IntStream.range(0, size).toArray();
mSlotsTop = size - 1;
}
public int add(T item) {
if (item == null)
return -1;
if (mSlotsTop = size)
throw new IndexOutOfBoundsException();
return mItems[i];
}
public int getIteratedIndex() {
return mIteratedIndex;
}
public boolean remove(int i) {
if (i size)
return false;
if (mItems[i] == null)
return false;
mItems[i] = null;
pushSlot(i);
return true;
}
public void remove(T item) {
remove(indexOf(item));
}
public boolean removeIterated() {
return remove(mIteratedIndex);
}
public boolean isFull() {
return mSlotsTop == -1;
}
public boolean isEmpty() {
return mSlotsTop == size - 1;
}
public int numFreeSlots() {
return mSlotsTop + 1;
}
public int indexOf(T item) {
for (int i = 0; i iterator() {
return new Iterator() {
private int index = -1;
{
if (mIteratedIndex != -1)
Solution
Potential bug #1
The problem of using a class variable
Potential bug #2
This is also related to
Potential bug #3
The other problem with having
Illustrating all bugs
Output:
When we have a new
The problem of using a class variable
mIteratedIndex that is modifiable in every new Iterator instance created is simply, multiple such instances cannot iterate through the contents reliably. Potential bug #2
This is also related to
Iterator in the hasNext() method: calling it twice without a next() effectively skips one element. Usually, the iteration state should not be modified when doing a hasNext(), but you have a index++ inside it.Potential bug #3
The other problem with having
index++ inside the hasNext() is that callers cannot reliably retrieve the next() element without calling hasNext() first.Illustrating all bugs
public static void main(String[] args) {
BucketArray instance = new BucketArray<>(String.class, 3);
instance.addAll("first", "middle", "last");
Iterator i1 = instance.iterator();
i1.hasNext();
i1.hasNext();
System.out.println(i1.next());
Iterator i2 = instance.iterator();
i2.hasNext();
System.out.println(i2.next());
System.out.println(i2.next());
i2.hasNext();
System.out.println(i2.next());
}Output:
middle
first
first
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3i1.hasNext() has to be called before i1.next(), else there will be an ArrayIndexOutOfBoundsException: -1 error. When i1.hasNext() is called twice in succession, "middle" is returned from calling i1.next(), skipping the first element.When we have a new
i2 Iterator, it starts from where i1 left off, which bizarrely returns "first" since that was stored as the final element of the internal array - is this expected? Regardless, calling i2.next() twice returns the same value, when it shouldn't. Finally, calling the pair of hasNext()/next() methods triggers the ArrayIndexOutOfBoundsException: 3 error as i2 would have iterated past the contents of the array.Code Snippets
public static void main(String[] args) {
BucketArray<String> instance = new BucketArray<>(String.class, 3);
instance.addAll("first", "middle", "last");
Iterator<String> i1 = instance.iterator();
i1.hasNext();
i1.hasNext();
System.out.println(i1.next());
Iterator<String> i2 = instance.iterator();
i2.hasNext();
System.out.println(i2.next());
System.out.println(i2.next());
i2.hasNext();
System.out.println(i2.next());
}middle
first
first
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3Context
StackExchange Code Review Q#106360, answer score: 2
Revisions (0)
No revisions yet.