added iterators

This commit is contained in:
Shautvast 2023-05-26 15:36:29 +02:00
parent 90ccb1015f
commit 610ce0ce41
16 changed files with 329 additions and 147 deletions

View file

@ -3,7 +3,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
import java.math.BigDecimal;
class BigDecimalHandler extends PrimitiveTypeHandler<BigDecimal> {
class BigDecimalHandler extends BuiltinTypeHandler<BigDecimal> {
public BigDecimalHandler(MethodHandle getter, MethodHandle setter) {
super(BigDecimal.class, getter, setter);
}

View file

@ -3,7 +3,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
import java.math.BigInteger;
class BigIntegerHandler extends PrimitiveTypeHandler<BigInteger> {
class BigIntegerHandler extends BuiltinTypeHandler<BigInteger> {
public BigIntegerHandler(MethodHandle getter, MethodHandle setter) {
super(BigInteger.class, getter, setter);
}

View file

@ -11,8 +11,8 @@ import java.lang.invoke.MethodHandle;
* of the bean that it needs to call 'runtime' (after instantiation of the list),
* ie. when a bean is added or retrieved from the list
*/
public abstract class PrimitiveTypeHandler<T> extends TypeHandler {
public PrimitiveTypeHandler(Class<?> type, MethodHandle getter, MethodHandle setter) {
public abstract class BuiltinTypeHandler<T> extends TypeHandler {
public BuiltinTypeHandler(Class<?> type, MethodHandle getter, MethodHandle setter) {
super(type, getter, setter);
}
@ -64,7 +64,7 @@ public abstract class PrimitiveTypeHandler<T> extends TypeHandler {
* Certain types can easily be stored as another known type, for instance
* a BigDecimal can be stored as a String.
* <p>
* The {@link PrimitiveTypeHandler} for BigDecimal would in that case be responsible for turning the String
* The {@link BuiltinTypeHandler} for BigDecimal would in that case be responsible for turning the String
* into a BigDecimal. It can do that by overriding this method
*
* @param value raw value to transform to the desired output type

View file

@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle;
/**
* Stores a byte value.
*/
class ByteHandler extends PrimitiveTypeHandler<Byte> {
class ByteHandler extends BuiltinTypeHandler<Byte> {
public ByteHandler(MethodHandle getter, MethodHandle setter) {
super(Byte.class, getter, setter);
@ -20,4 +20,12 @@ class ByteHandler extends PrimitiveTypeHandler<Byte> {
public void setValue(Object instance, Object value) {
super.setValue(instance, ((Long) value).byteValue());
}
@Override
public Object transform(Object value) {
if (value instanceof Long) {
return ((Long) value).byteValue();
}
return value;
}
}

View file

@ -17,7 +17,7 @@ class CompoundTypeHandler extends TypeHandler {
return properties.values();
}
void addHandler(String propertyName, PrimitiveTypeHandler<?> primitiveType) {
void addHandler(String propertyName, BuiltinTypeHandler<?> primitiveType) {
properties.put(propertyName, primitiveType);
}

View file

@ -6,7 +6,6 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.UnaryOperator;
//notes:
//1. should find out growth factor of arraylist
@ -25,7 +24,9 @@ import java.util.function.UnaryOperator;
* <p>
* Employs the SQLite style of data storage, most notably integer numbers are stored with variable byte length
* <p>
* The classes stored in {@link ContiguousList} MUST have a no-args constructor.
* The classes stored in {@link ContiguousList} MUST have a no-args constructor. (so sorry)
* // There is (was?) a way to create instances without a no-args constructor. I have used it somewhere in the past...
* // I think {@link java.io.ObjectInputStream} uses it.
* <p>
* Like ArrayList, mutating operations are not synchronized.
* <p>
@ -35,7 +36,7 @@ import java.util.function.UnaryOperator;
* performance-wise, like the indexed add and set methods. They mess with the memory layout. The list is meant to
* be appended at the tail.
*/
public class ContiguousList<E> implements List<E> {
public class ContiguousList<E> extends NotImplementedList<E> implements List<E> {
private static final byte[] DOUBLE_TYPE = {7};
private static final byte[] FLOAT_TYPE = {10}; // not in line with SQLite anymore
@ -49,17 +50,17 @@ public class ContiguousList<E> implements List<E> {
*/
private ByteBuffer data = ByteBuffer.allocate(32);
private int currentElementIndex;
private int currentElementValueIndex;
private int[] elementIndices = new int[10];
private int size;
private TypeHandler type;
private TypeHandler rootHandler;
public ContiguousList(Class<E> type) {
inspectType(type);
elementIndices[0] = currentElementIndex; // index of first element
elementIndices[0] = currentElementValueIndex; // index of first element
}
/*
@ -72,10 +73,10 @@ public class ContiguousList<E> implements List<E> {
*/
private void inspectType(Class<?> type) {
if (PropertyHandlerFactory.isKnownType(type)) {
this.type = PropertyHandlerFactory.forType(type);
this.rootHandler = PropertyHandlerFactory.forType(type);
} else {
CompoundTypeHandler compoundType = new CompoundTypeHandler(type);
this.type = compoundType;
this.rootHandler = compoundType;
try {
addPropertyHandlersForCompoundType(type, compoundType);
} catch (IllegalAccessException e) {
@ -94,7 +95,7 @@ public class ContiguousList<E> implements List<E> {
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
if (PropertyHandlerFactory.isKnownType(fieldType)) {
PrimitiveTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, getter, setter);
BuiltinTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, getter, setter);
parentCompoundType.addHandler(field.getName(), primitiveType);
} else {
@ -111,36 +112,31 @@ public class ContiguousList<E> implements List<E> {
});
}
@Override
@SuppressWarnings("Contract")
public boolean add(E element) {
if (element == null) {
return false;
}
getProperties(element, type);
getProperties(element, rootHandler);
size += 1;
// keep track of where the objects are stored
if (elementIndices.length < size + 1) {
this.elementIndices = Arrays.copyOf(this.elementIndices, this.elementIndices.length * 2);
}
elementIndices[size] = currentElementIndex;
elementIndices[size] = currentElementValueIndex;
return true;
}
private void getProperties(Object element, TypeHandler type) {
// passed type is primitive
//TODO rename primitive to builtin
if (type instanceof PrimitiveTypeHandler<?>) {
((PrimitiveTypeHandler<?>) type).storePropertyValue(element, this);
private void getProperties(Object element, TypeHandler typeHandler) {
if (typeHandler instanceof BuiltinTypeHandler<?>) {
((BuiltinTypeHandler<?>) typeHandler).storePropertyValue(element, this);
} else {
// passed type is compund ie. has child properties
((CompoundTypeHandler)type).getProperties().forEach(property -> {
if (property instanceof PrimitiveTypeHandler<?>) {
// recurse once more -> property is stored
getProperties(element, property);
//could easily inline this
// passed type is compound ie. has child properties
((CompoundTypeHandler) typeHandler).getProperties().forEach(property -> {
if (property instanceof BuiltinTypeHandler<?>) {
((BuiltinTypeHandler<?>) property).storePropertyValue(element, this);
} else {
CompoundTypeHandler child = ((CompoundTypeHandler) property);
try {
@ -154,17 +150,16 @@ public class ContiguousList<E> implements List<E> {
}
}
@Override
public boolean remove(Object o) {
throw new RuntimeException("Not yet implemented");
}
@Override
@SuppressWarnings("NullableProblems")
public boolean containsAll(Collection<?> collection) {
throw new RuntimeException("Not yet implemented");
}
/**
* Get element at specified index.
* <p>
* Please note that this creates a new instance using the stored element data and is therefore
* not the recommended usecase because of the performance penalty. It's implemented for convenience, but
* there are alternatives such as the propertyIterator and getXX...[implement]
*
* @param index The index of the element data
* @return a new element instance
*/
@Override
@SuppressWarnings("unchecked")
public E get(int index) {
@ -173,14 +168,15 @@ public class ContiguousList<E> implements List<E> {
}
data.position(elementIndices[index]);
try {
if (type instanceof PrimitiveTypeHandler<?>) {
return (E)((PrimitiveTypeHandler<?>)type).transform(ValueReader.read(data));
if (rootHandler instanceof BuiltinTypeHandler<?>) {
Object read = ValueReader.read(data);
return (E) ((BuiltinTypeHandler<?>) rootHandler).transform(read);
}
// create a new instance of the list element type
E newInstance = (E) type.getType().getDeclaredConstructor().newInstance();
E newInstance = (E) rootHandler.getType().getDeclaredConstructor().newInstance();
// set the data
setProperties(newInstance, (CompoundTypeHandler) type);
setProperties(newInstance, (CompoundTypeHandler) rootHandler);
return newInstance;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
@ -191,8 +187,8 @@ public class ContiguousList<E> implements List<E> {
private void setProperties(Object element, CompoundTypeHandler compoundType) {
compoundType.getProperties().forEach(property -> {
if (property instanceof PrimitiveTypeHandler) {
PrimitiveTypeHandler<?> type =((PrimitiveTypeHandler<?>) property);
if (property instanceof BuiltinTypeHandler) {
BuiltinTypeHandler<?> type = ((BuiltinTypeHandler<?>) property);
type.setValue(element, ValueReader.read(data));
} else {
try {
@ -212,6 +208,65 @@ public class ContiguousList<E> implements List<E> {
});
}
/**
* Returns an {@link Iterator} over the property values in the List. That is, it iterates all
* bean property values in a fixed order for all elements.
* <p>
* Because the values differ in type the output type is Object
*
* NB the actual type (right now) is the `raw` value: all integers are of type Long, BigInteger is String
* // That is unfortunate (or must I say: annoying!), but for something like JSON not a problem (I think).
* // So maybe keep this in (say 'rawValueIterator') and also create a typesafe iterator.
* <p>
* It detects {@link ConcurrentModificationException} if the underlying list was updated while iterating.
* <p>
* // I should probably include a type so that the caller could cast to the correct type
* // not sure yet
*
* @return an Iterator<?>
*/
public Iterator<?> valueIterator() {
return new ValueIterator();
}
class ValueIterator implements Iterator<Object> {
private final int originalSize;
private final int originalPosition;
ValueIterator() {
this.originalSize = size;
this.originalPosition = data.position();
data.position(0);
}
@Override
public boolean hasNext() {
return data.position() < originalPosition;
}
@Override
public Object next() {
if (originalSize != size) {
throw new ConcurrentModificationException("Modifications detected while iterating.");
}
/* The following depends on the bytebuffer position. Calling add(..) would mess it up
* so that's why we first check for modifications (me and the computer)
*
* I could also maintain the position here. But you main want to fail ... dunno */
return ValueReader.read(data);
}
}
/**
* Returns an {@link Iterator} over the property values of the specified element in the List.
*
* @return
*/
public Iterator<Object> valueIterator(int index) {
//TODO
return null;
}
public boolean addAll(Collection<? extends E> collection) {
for (E element : collection) {
add(element);
@ -219,84 +274,11 @@ public class ContiguousList<E> implements List<E> {
return true;
}
@Override
@SuppressWarnings("NullableProblems")
public boolean addAll(int i, Collection<? extends E> collection) {
throw new RuntimeException("Not yet implemented");
}
@Override
@SuppressWarnings("NullableProblems")
public boolean removeAll(Collection<?> collection) {
throw new RuntimeException("Not implemented");
}
@Override
@SuppressWarnings("NullableProblems")
public boolean retainAll(Collection<?> collection) {
throw new RuntimeException("Not implemented");
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
throw new RuntimeException("Not yet implemented");
}
@Override
public void sort(Comparator<? super E> c) {
throw new RuntimeException("Not implemented");
}
public void clear() {
this.currentElementIndex = 0;
this.currentElementValueIndex = 0;
this.size = 0;
}
@Override
public E set(int i, E e) {
throw new RuntimeException("Not implemented");
}
@Override
public void add(int i, E e) {
throw new RuntimeException("Not implemented");
}
@Override
public E remove(int i) {
throw new RuntimeException("Not implemented");
}
@Override
public int indexOf(Object o) {
throw new RuntimeException("Not implemented");
}
@Override
public int lastIndexOf(Object o) {
throw new RuntimeException("Not implemented");
}
@Override
public ListIterator<E> listIterator() {
throw new RuntimeException("Not yet implemented");
}
@Override
public ListIterator<E> listIterator(int i) {
throw new RuntimeException("Not yet implemented");
}
@Override
public List<E> subList(int i, int i1) {
throw new RuntimeException("Not yet implemented");
}
@Override
public Spliterator<E> spliterator() {
return List.super.spliterator();
}
public int size() {
return size;
}
@ -306,14 +288,9 @@ public class ContiguousList<E> implements List<E> {
return size == 0;
}
@Override
public boolean contains(Object o) {
throw new RuntimeException("Not implemented");
}
@Override
public Iterator<E> iterator() {
return new Iter<>();
return new ElementIterator<>();
}
@Override
@ -338,9 +315,15 @@ public class ContiguousList<E> implements List<E> {
}
class Iter<F> implements Iterator<F> {
class ElementIterator<F> implements Iterator<F> {
private int curIndex = 0;
private final int originalSize;
ElementIterator() {
this.originalSize = size;
data.position(0);
}
@Override
public boolean hasNext() {
@ -356,15 +339,15 @@ public class ContiguousList<E> implements List<E> {
private void store(byte[] bytes) {
ensureFree(bytes.length);
data.position(currentElementIndex); // ensures intermittent reads/writes
data.position(currentElementValueIndex); // ensures intermittent reads/writes are safe
data.put(bytes);
currentElementIndex += bytes.length;
currentElementValueIndex += bytes.length;
}
private void store0() {
ensureFree(1);
data.put((byte) 0);
currentElementIndex += 1;
currentElementValueIndex += 1;
}
void storeString(String value) {
@ -436,7 +419,7 @@ public class ContiguousList<E> implements List<E> {
}
byte[] getData() {
return Arrays.copyOfRange(data.array(), 0, currentElementIndex);
return Arrays.copyOfRange(data.array(), 0, currentElementValueIndex);
}
int[] getElementIndices() {
@ -444,7 +427,7 @@ public class ContiguousList<E> implements List<E> {
}
private void ensureFree(int length) {
while (currentElementIndex + length > data.capacity()) {
while (currentElementValueIndex + length > data.capacity()) {
byte[] bytes = this.data.array();
this.data = ByteBuffer.allocate(this.data.capacity() * 2);
this.data.put(bytes);

View file

@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle;
/**
* Stores a double value.
*/
class DoubleHandler extends PrimitiveTypeHandler<Double> {
class DoubleHandler extends BuiltinTypeHandler<Double> {
public DoubleHandler(MethodHandle getter, MethodHandle setter) {
super(Double.class, getter, setter);
}

View file

@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
class FloatHandler extends PrimitiveTypeHandler<Float> {
class FloatHandler extends BuiltinTypeHandler<Float> {
public FloatHandler(MethodHandle getter, MethodHandle setter) {
super(Float.class, getter, setter);
}

View file

@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
class IntegerHandler extends PrimitiveTypeHandler<Integer> {
class IntegerHandler extends BuiltinTypeHandler<Integer> {
public IntegerHandler(MethodHandle getter, MethodHandle setter) {
super(Integer.class, getter, setter);
}
@ -20,4 +20,14 @@ class IntegerHandler extends PrimitiveTypeHandler<Integer> {
public void setValue(Object instance, Object value) {
super.setValue(instance, ((Long) value).intValue());
}
@Override
public Object transform(Object value) {
// could be Long (raw value)
// or Integer when it's a property with known type
if (value instanceof Long) {
return ((Long) value).intValue();
}
return value;
}
}

View file

@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
class LongHandler extends PrimitiveTypeHandler<Long> {
class LongHandler extends BuiltinTypeHandler<Long> {
public LongHandler(MethodHandle getter, MethodHandle setter) {
super(Long.class, getter, setter);
}

View file

@ -0,0 +1,117 @@
package nl.sanderhautvast.contiguous;
import java.util.*;
import java.util.function.UnaryOperator;
/**
* Base class that is a list of all the methods live that will likely not be implemented (pun intended)
* Only purpose: reduce linecount in the subclass.
*
* @param <E>
*/
public abstract class NotImplementedList<E> implements List<E> {
@Override
public boolean contains(Object o) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible: iterate, create instance, then compare ??
}
@Override
public Spliterator<E> spliterator() {
return List.super.spliterator();
// not sure about this yet
}
@Override
public boolean remove(Object o) {
throw new RuntimeException("Not yet implemented");
// is possible, but not feasible: iterate, create instance, then compare ??
// and then removing, which requires moving a lot of bytes
}
@Override
@SuppressWarnings("NullableProblems")
public boolean containsAll(Collection<?> collection) {
throw new RuntimeException("Not yet implemented");
// is possible, but not feasible: iterate, create instance, then compare ??
}
@Override
public boolean addAll(int i, Collection<? extends E> collection) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public boolean removeAll(Collection<?> collection) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public boolean retainAll(Collection<?> collection) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public E set(int i, E e) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public void add(int i, E e) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public E remove(int i) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible because it would require moving a lot of bytes
}
@Override
public int indexOf(Object o) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible: iterate, create instance, then compare ??
}
@Override
public int lastIndexOf(Object o) {
throw new RuntimeException("Not implemented");
// is possible, but not feasible
}
@Override
public ListIterator<E> listIterator() {
throw new RuntimeException("Not implemented");
// ListIterator contains remove, so not possible
}
@Override
public ListIterator<E> listIterator(int i) {
throw new RuntimeException("Not yet implemented");
// ListIterator contains remove, so not possible
}
@Override
public void sort(Comparator<? super E> c) {
throw new RuntimeException("Not implemented");
// an immutable sort would be an option
}
@Override
public List<E> subList(int i, int i1) {
throw new RuntimeException("Not yet implemented");
// possible
}
}

View file

@ -11,7 +11,7 @@ import java.util.Map;
* Maps the propertyvalue type to a PropertyHandler
*/
final class PropertyHandlerFactory {
private static final Map<Class<?>, Class<? extends PrimitiveTypeHandler<?>>> TYPE_HANDLERS = new HashMap<>();
private static final Map<Class<?>, Class<? extends BuiltinTypeHandler<?>>> TYPE_HANDLERS = new HashMap<>();
private PropertyHandlerFactory() {
}
@ -41,13 +41,13 @@ final class PropertyHandlerFactory {
return TYPE_HANDLERS.containsKey(type);
}
public static <T> PrimitiveTypeHandler<T> forType(Class<T> type, MethodHandle getter, MethodHandle setter) {
public static <T> BuiltinTypeHandler<T> forType(Class<T> type, MethodHandle getter, MethodHandle setter) {
try {
Class<? extends PrimitiveTypeHandler<?>> appenderClass = TYPE_HANDLERS.get(type);
Class<? extends BuiltinTypeHandler<?>> appenderClass = TYPE_HANDLERS.get(type);
if (appenderClass == null) {
throw new IllegalStateException("No Handler for " + type.getName());
}
return (PrimitiveTypeHandler<T>) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class)
return (BuiltinTypeHandler<T>) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class)
.newInstance(getter, setter);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException e) {
@ -55,14 +55,14 @@ final class PropertyHandlerFactory {
}
}
public static <T> PrimitiveTypeHandler<T> forType(Class<T> type) {
public static <T> BuiltinTypeHandler<T> forType(Class<T> type) {
return forType(type, null, null);
}
/**
* register a new TypeHandler that cannot be derived from bean properties
*/
public static void register(Class<?> type, Class<? extends PrimitiveTypeHandler<?>> typehandler) {
public static void register(Class<?> type, Class<? extends BuiltinTypeHandler<?>> typehandler) {
TYPE_HANDLERS.put(type, typehandler);
}
}

View file

@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
class ShortHandler extends PrimitiveTypeHandler<Short> {
class ShortHandler extends BuiltinTypeHandler<Short> {
public ShortHandler(MethodHandle getter, MethodHandle setter) {
super(Short.class, getter, setter);
}
@ -16,4 +16,12 @@ class ShortHandler extends PrimitiveTypeHandler<Short> {
public void setValue(Object instance, Object value) {
super.setValue(instance, ((Long) value).shortValue());
}
@Override
public Object transform(Object value) {
if (value instanceof Long) {
return ((Long) value).shortValue();
}
return value;
}
}

View file

@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
import java.lang.invoke.MethodHandle;
class StringHandler extends PrimitiveTypeHandler<String> {
class StringHandler extends BuiltinTypeHandler<String> {
public StringHandler(MethodHandle getter, MethodHandle setter) {
super(String.class, getter, setter);
}

View file

@ -40,9 +40,9 @@ class ValueReader {
} else if (columnType == 7) {
return buffer.getDouble();
} else if (columnType == 8) {
return 0;
return 0L; //has to be long!
} else if (columnType == 9) {
return 1;
return 1L;
} else if (columnType == 10) {
return buffer.getFloat();
} else if (columnType >= 12 && columnType % 2 == 0) {

View file

@ -3,6 +3,7 @@ package nl.sanderhautvast.contiguous;
import org.junit.jupiter.api.Test;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@ -141,4 +142,59 @@ public class ContiguousListTest {
bigIntegers.add(new BigInteger("1000000000"));
assertEquals(1_000_000_000L, bigIntegers.get(0).longValue());
}
@Test
public void testIterator() {
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
for (int i = 0; i < 100; i++) {
integers.add(i);
}
int prevValue = -1;
for (int value : integers) {
assertEquals(prevValue, value - 1);
prevValue = value;
}
integers.add(100);
assertEquals(100, integers.get(100));
}
@Test
public void testPrimitiveIterator() {
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
for (int i = 0; i < 100; i++) {
integers.add(i);
}
long prevValue = -1;
for (Iterator<?> intIter = integers.valueIterator(); intIter.hasNext(); ) {
long value = (long) intIter.next();
assertEquals(prevValue, value - 1);
prevValue = value;
}
integers.add(100);
assertEquals(100, integers.get(100));
}
@Test
public void testCompoundValueIterator() {
ContiguousList<IntBean> integers = new ContiguousList<>(IntBean.class);
for (int i = 0; i < 100; i++) {
integers.add(new IntBean(i));
}
long prevValue = -1;
for (Iterator<?> intIter = integers.valueIterator(); intIter.hasNext(); ) {
long value = (long) intIter.next(); // here a value (IntBean.value)
assertEquals(prevValue, value - 1);
prevValue = value;
}
integers.add(new IntBean(100));
assertEquals(new IntBean(100), integers.get(100)); // here an instance
}
}