mirror of
https://github.com/maxkratz/fastutil.git
synced 2024-09-16 11:58:09 +00:00
A very long-standing bug in linked hash containers has been fixed
This commit is contained in:
parent
4f2b7e2604
commit
d6c4cffd9a
7 changed files with 116 additions and 70 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -10,3 +10,9 @@ dist
|
||||||
docs
|
docs
|
||||||
build
|
build
|
||||||
bin
|
bin
|
||||||
|
fastutil-*.jar
|
||||||
|
fastutil*.txt
|
||||||
|
pom-*.xml
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.ant-targets-build.xml
|
||||||
|
|
6
CHANGES
6
CHANGES
|
@ -5,6 +5,12 @@
|
||||||
- HashCommon.nextPowerOf2() is now faster. Thanks to Richard Startin
|
- HashCommon.nextPowerOf2() is now faster. Thanks to Richard Startin
|
||||||
for improving this method.
|
for improving this method.
|
||||||
|
|
||||||
|
- A very long-standing bug in linked hash containers has been fixed.
|
||||||
|
Methods removing the last or first entry would not update correctly
|
||||||
|
the pointer to the first (or last, respectively) item, leading to
|
||||||
|
incorrect iteration behavior when removing the last element of a
|
||||||
|
container.
|
||||||
|
|
||||||
8.5.10
|
8.5.10
|
||||||
|
|
||||||
- Really fixed overflow bug in BigArrays.ensureOffsetLength(). Thanks
|
- Really fixed overflow bug in BigArrays.ensureOffsetLength(). Thanks
|
||||||
|
|
|
@ -3,7 +3,7 @@ javadoc.base=/usr/share/javadoc
|
||||||
|
|
||||||
build.sysclasspath=ignore
|
build.sysclasspath=ignore
|
||||||
|
|
||||||
version=8.5.9
|
version=8.5.11
|
||||||
|
|
||||||
dist=dist
|
dist=dist
|
||||||
src=src
|
src=src
|
||||||
|
|
|
@ -755,12 +755,17 @@ public class OPEN_HASH_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP KEY_VALUE_GENE
|
||||||
public VALUE_GENERIC_TYPE REMOVE_FIRST_VALUE() {
|
public VALUE_GENERIC_TYPE REMOVE_FIRST_VALUE() {
|
||||||
if (size == 0) throw new NoSuchElementException();
|
if (size == 0) throw new NoSuchElementException();
|
||||||
final int pos = first;
|
final int pos = first;
|
||||||
|
|
||||||
// Abbreviated version of fixPointers(pos)
|
// Abbreviated version of fixPointers(pos)
|
||||||
first = GET_NEXT(link[pos]);
|
if (size == 1) first = last = -1;
|
||||||
if (0 <= first) {
|
else {
|
||||||
// Special case of SET_PREV(link[first], -1)
|
first = GET_NEXT(link[pos]);
|
||||||
link[first] |= (-1 & 0xFFFFFFFFL) << 32;
|
if (0 <= first) {
|
||||||
|
// Special case of SET_PREV(link[first], -1)
|
||||||
|
link[first] |= (-1 & 0xFFFFFFFFL) << 32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size--;
|
size--;
|
||||||
final VALUE_GENERIC_TYPE v = value[pos];
|
final VALUE_GENERIC_TYPE v = value[pos];
|
||||||
if (pos == n) {
|
if (pos == n) {
|
||||||
|
@ -784,12 +789,17 @@ public class OPEN_HASH_MAP KEY_VALUE_GENERIC extends ABSTRACT_MAP KEY_VALUE_GENE
|
||||||
public VALUE_GENERIC_TYPE REMOVE_LAST_VALUE() {
|
public VALUE_GENERIC_TYPE REMOVE_LAST_VALUE() {
|
||||||
if (size == 0) throw new NoSuchElementException();
|
if (size == 0) throw new NoSuchElementException();
|
||||||
final int pos = last;
|
final int pos = last;
|
||||||
|
|
||||||
// Abbreviated version of fixPointers(pos)
|
// Abbreviated version of fixPointers(pos)
|
||||||
last = GET_PREV(link[pos]);
|
if (size == 1) first = last = -1;
|
||||||
if (0 <= last) {
|
else {
|
||||||
// Special case of SET_NEXT(link[last], -1)
|
last = GET_PREV(link[pos]);
|
||||||
link[last] |= -1 & 0xFFFFFFFFL;
|
if (0 <= last) {
|
||||||
|
// Special case of SET_NEXT(link[last], -1)
|
||||||
|
link[last] |= -1 & 0xFFFFFFFFL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size--;
|
size--;
|
||||||
final VALUE_GENERIC_TYPE v = value[pos];
|
final VALUE_GENERIC_TYPE v = value[pos];
|
||||||
if (pos == n) {
|
if (pos == n) {
|
||||||
|
|
|
@ -1016,12 +1016,17 @@ public class OPEN_HASH_SET KEY_GENERIC extends ABSTRACT_SET KEY_GENERIC implemen
|
||||||
public KEY_GENERIC_TYPE REMOVE_FIRST_KEY() {
|
public KEY_GENERIC_TYPE REMOVE_FIRST_KEY() {
|
||||||
if (size == 0) throw new NoSuchElementException();
|
if (size == 0) throw new NoSuchElementException();
|
||||||
final int pos = first;
|
final int pos = first;
|
||||||
|
|
||||||
// Abbreviated version of fixPointers(pos)
|
// Abbreviated version of fixPointers(pos)
|
||||||
first = GET_NEXT(link[pos]);
|
if (size == 1) first = last = -1;
|
||||||
if (0 <= first) {
|
else {
|
||||||
// Special case of SET_PREV(link[first], -1)
|
first = GET_NEXT(link[pos]);
|
||||||
link[first] |= (-1 & 0xFFFFFFFFL) << 32;
|
if (0 <= first) {
|
||||||
|
// Special case of SET_PREV(link[first], -1)
|
||||||
|
link[first] |= (-1 & 0xFFFFFFFFL) << 32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final KEY_GENERIC_TYPE k = key[pos];
|
final KEY_GENERIC_TYPE k = key[pos];
|
||||||
size--;
|
size--;
|
||||||
if (KEY_EQUALS_NULL(k)) {
|
if (KEY_EQUALS_NULL(k)) {
|
||||||
|
@ -1040,12 +1045,17 @@ public class OPEN_HASH_SET KEY_GENERIC extends ABSTRACT_SET KEY_GENERIC implemen
|
||||||
public KEY_GENERIC_TYPE REMOVE_LAST_KEY() {
|
public KEY_GENERIC_TYPE REMOVE_LAST_KEY() {
|
||||||
if (size == 0) throw new NoSuchElementException();
|
if (size == 0) throw new NoSuchElementException();
|
||||||
final int pos = last;
|
final int pos = last;
|
||||||
|
|
||||||
// Abbreviated version of fixPointers(pos)
|
// Abbreviated version of fixPointers(pos)
|
||||||
last = GET_PREV(link[pos]);
|
if (size == 1) first = last = -1;
|
||||||
if (0 <= last) {
|
else {
|
||||||
// Special case of SET_NEXT(link[last], -1)
|
last = GET_PREV(link[pos]);
|
||||||
link[last] |= -1 & 0xFFFFFFFFL;
|
if (0 <= last) {
|
||||||
|
// Special case of SET_NEXT(link[last], -1)
|
||||||
|
link[last] |= -1 & 0xFFFFFFFFL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final KEY_GENERIC_TYPE k = key[pos];
|
final KEY_GENERIC_TYPE k = key[pos];
|
||||||
size--;
|
size--;
|
||||||
if (KEY_EQUALS_NULL(k)) {
|
if (KEY_EQUALS_NULL(k)) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntMap.Entry;
|
||||||
public class Int2IntLinkedOpenHashMapTest {
|
public class Int2IntLinkedOpenHashMapTest {
|
||||||
@Test
|
@Test
|
||||||
public void testContainsValue() {
|
public void testContainsValue() {
|
||||||
Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(Hash.DEFAULT_INITIAL_SIZE);
|
final Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
assertEquals(0, m.put(0, 2));
|
assertEquals(0, m.put(0, 2));
|
||||||
assertEquals(0, m.put(1, 3));
|
assertEquals(0, m.put(1, 3));
|
||||||
assertTrue(m.containsValue(2));
|
assertTrue(m.containsValue(2));
|
||||||
|
@ -86,7 +86,7 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWrapAround() {
|
public void testWrapAround() {
|
||||||
Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(4, .5f);
|
final Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(4, .5f);
|
||||||
assertEquals(8, m.n);
|
assertEquals(8, m.n);
|
||||||
// The following code inverts HashCommon.phiMix() and places strategically keys in slots 6, 7 and 0
|
// The following code inverts HashCommon.phiMix() and places strategically keys in slots 6, 7 and 0
|
||||||
m.put(HashCommon.invMix(6), 0);
|
m.put(HashCommon.invMix(6), 0);
|
||||||
|
@ -95,9 +95,9 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
assertNotEquals(0, m.key[0]);
|
assertNotEquals(0, m.key[0]);
|
||||||
assertNotEquals(0, m.key[6]);
|
assertNotEquals(0, m.key[6]);
|
||||||
assertNotEquals(0, m.key[7]);
|
assertNotEquals(0, m.key[7]);
|
||||||
IntOpenHashSet keys = new IntOpenHashSet(m.keySet());
|
final IntOpenHashSet keys = new IntOpenHashSet(m.keySet());
|
||||||
IntIterator iterator = m.keySet().iterator();
|
final IntIterator iterator = m.keySet().iterator();
|
||||||
IntOpenHashSet t = new IntOpenHashSet();
|
final IntOpenHashSet t = new IntOpenHashSet();
|
||||||
t.add(iterator.nextInt());
|
t.add(iterator.nextInt());
|
||||||
t.add(iterator.nextInt());
|
t.add(iterator.nextInt());
|
||||||
// Originally, this remove would move the entry in slot 0 in slot 6 and we would return the entry in 0 twice
|
// Originally, this remove would move the entry in slot 0 in slot 6 and we would return the entry in 0 twice
|
||||||
|
@ -108,7 +108,7 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWrapAround2() {
|
public void testWrapAround2() {
|
||||||
Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(4, .75f);
|
final Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(4, .75f);
|
||||||
assertEquals(8, m.n);
|
assertEquals(8, m.n);
|
||||||
// The following code inverts HashCommon.phiMix() and places strategically keys in slots 4, 5, 6, 7 and 0
|
// The following code inverts HashCommon.phiMix() and places strategically keys in slots 4, 5, 6, 7 and 0
|
||||||
m.put(HashCommon.invMix(4), 0);
|
m.put(HashCommon.invMix(4), 0);
|
||||||
|
@ -122,9 +122,9 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
assertNotEquals(0, m.key[6]);
|
assertNotEquals(0, m.key[6]);
|
||||||
assertNotEquals(0, m.key[7]);
|
assertNotEquals(0, m.key[7]);
|
||||||
//System.err.println(Arraym.toString(m.key));
|
//System.err.println(Arraym.toString(m.key));
|
||||||
IntOpenHashSet keys = new IntOpenHashSet(m.keySet());
|
final IntOpenHashSet keys = new IntOpenHashSet(m.keySet());
|
||||||
IntIterator iterator = m.keySet().iterator();
|
final IntIterator iterator = m.keySet().iterator();
|
||||||
IntOpenHashSet t = new IntOpenHashSet();
|
final IntOpenHashSet t = new IntOpenHashSet();
|
||||||
assertTrue(t.add(iterator.nextInt()));
|
assertTrue(t.add(iterator.nextInt()));
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
//System.err.println(Arraym.toString(m.key));
|
//System.err.println(Arraym.toString(m.key));
|
||||||
|
@ -143,7 +143,7 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWrapAround3() {
|
public void testWrapAround3() {
|
||||||
Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(4, .75f);
|
final Int2IntLinkedOpenHashMap m = new Int2IntLinkedOpenHashMap(4, .75f);
|
||||||
assertEquals(8, m.n);
|
assertEquals(8, m.n);
|
||||||
// The following code inverts HashCommon.phiMix() and places strategically keys in slots 5, 6, 7, 0 and 1
|
// The following code inverts HashCommon.phiMix() and places strategically keys in slots 5, 6, 7, 0 and 1
|
||||||
m.put(HashCommon.invMix(5), 0);
|
m.put(HashCommon.invMix(5), 0);
|
||||||
|
@ -157,9 +157,9 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
assertNotEquals(0, m.key[0]);
|
assertNotEquals(0, m.key[0]);
|
||||||
assertNotEquals(0, m.key[1]);
|
assertNotEquals(0, m.key[1]);
|
||||||
//System.err.println(Arraym.toString(m.key));
|
//System.err.println(Arraym.toString(m.key));
|
||||||
IntOpenHashSet keys = new IntOpenHashSet(m.keySet());
|
final IntOpenHashSet keys = new IntOpenHashSet(m.keySet());
|
||||||
IntIterator iterator = m.keySet().iterator();
|
final IntIterator iterator = m.keySet().iterator();
|
||||||
IntOpenHashSet t = new IntOpenHashSet();
|
final IntOpenHashSet t = new IntOpenHashSet();
|
||||||
assertTrue(t.add(iterator.nextInt()));
|
assertTrue(t.add(iterator.nextInt()));
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
//System.err.println(Arraym.toString(m.key));
|
//System.err.println(Arraym.toString(m.key));
|
||||||
|
@ -187,16 +187,24 @@ public class Int2IntLinkedOpenHashMapTest {
|
||||||
m.int2IntEntrySet().forEach(new Consumer<Int2IntMap.Entry>() {
|
m.int2IntEntrySet().forEach(new Consumer<Int2IntMap.Entry>() {
|
||||||
int i = a.length;
|
int i = a.length;
|
||||||
@Override
|
@Override
|
||||||
public void accept(Entry t) {
|
public void accept(final Entry t) {
|
||||||
assertEquals(--i, t.getIntKey());
|
assertEquals(--i, t.getIntKey());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m.int2IntEntrySet().fastForEach(new Consumer<Int2IntMap.Entry>() {
|
m.int2IntEntrySet().fastForEach(new Consumer<Int2IntMap.Entry>() {
|
||||||
int i = a.length;
|
int i = a.length;
|
||||||
@Override
|
@Override
|
||||||
public void accept(Entry t) {
|
public void accept(final Entry t) {
|
||||||
assertEquals(--i, t.getIntKey());
|
assertEquals(--i, t.getIntKey());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveLast() {
|
||||||
|
final Int2IntLinkedOpenHashMap s = new Int2IntLinkedOpenHashMap();
|
||||||
|
s.put(0, 0);
|
||||||
|
s.removeLastInt();
|
||||||
|
assertFalse(s.int2IntEntrySet().iterator().hasNext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
@Test
|
@Test
|
||||||
public void testStrangeRetainAllCase() {
|
public void testStrangeRetainAllCase() {
|
||||||
|
|
||||||
IntArrayList initialElements = IntArrayList.wrap(new int[] { 586, 940,
|
final IntArrayList initialElements = IntArrayList.wrap(new int[] { 586, 940,
|
||||||
1086, 1110, 1168, 1184, 1185, 1191, 1196, 1229, 1237, 1241,
|
1086, 1110, 1168, 1184, 1185, 1191, 1196, 1229, 1237, 1241,
|
||||||
1277, 1282, 1284, 1299, 1308, 1309, 1310, 1314, 1328, 1360,
|
1277, 1282, 1284, 1299, 1308, 1309, 1310, 1314, 1328, 1360,
|
||||||
1366, 1370, 1378, 1388, 1392, 1402, 1406, 1411, 1426, 1437,
|
1366, 1370, 1378, 1388, 1392, 1402, 1406, 1411, 1426, 1437,
|
||||||
|
@ -57,11 +57,11 @@ public class IntLinkedOpenHashSetTest {
|
||||||
7094, 7379, 7384, 7388, 7394, 7414, 7419, 7458, 7459, 7466,
|
7094, 7379, 7384, 7388, 7394, 7414, 7419, 7458, 7459, 7466,
|
||||||
7467 });
|
7467 });
|
||||||
|
|
||||||
IntArrayList retainElements = IntArrayList.wrap(new int[] { 586 });
|
final IntArrayList retainElements = IntArrayList.wrap(new int[] { 586 });
|
||||||
|
|
||||||
// Initialize both implementations with the same data
|
// Initialize both implementations with the same data
|
||||||
IntLinkedOpenHashSet instance = new IntLinkedOpenHashSet(initialElements);
|
final IntLinkedOpenHashSet instance = new IntLinkedOpenHashSet(initialElements);
|
||||||
IntRBTreeSet referenceInstance = new IntRBTreeSet(initialElements);
|
final IntRBTreeSet referenceInstance = new IntRBTreeSet(initialElements);
|
||||||
|
|
||||||
instance.retainAll(retainElements);
|
instance.retainAll(retainElements);
|
||||||
referenceInstance.retainAll(retainElements);
|
referenceInstance.retainAll(retainElements);
|
||||||
|
@ -83,10 +83,10 @@ public class IntLinkedOpenHashSetTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "deprecation" })
|
@SuppressWarnings({ "unchecked", "deprecation" })
|
||||||
private static void test(int n, float f) throws IOException, ClassNotFoundException {
|
private static void test(final int n, final float f) throws IOException, ClassNotFoundException {
|
||||||
int c;
|
int c;
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE, f);
|
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE, f);
|
||||||
java.util.Set<Integer> t = new java.util.LinkedHashSet<>();
|
final java.util.Set<Integer> t = new java.util.LinkedHashSet<>();
|
||||||
/* First of all, we fill t with random data. */
|
/* First of all, we fill t with random data. */
|
||||||
for (int i = 0; i < f * n; i++)
|
for (int i = 0; i < f * n; i++)
|
||||||
t.add((Integer.valueOf(genKey())));
|
t.add((Integer.valueOf(genKey())));
|
||||||
|
@ -95,14 +95,13 @@ public class IntLinkedOpenHashSetTest {
|
||||||
assertTrue("Error: !m.equals(t) after insertion", s.equals(t));
|
assertTrue("Error: !m.equals(t) after insertion", s.equals(t));
|
||||||
assertTrue("Error: !t.equals(m) after insertion", t.equals(s));
|
assertTrue("Error: !t.equals(m) after insertion", t.equals(s));
|
||||||
/* Now we check that m actually holds that data. */
|
/* Now we check that m actually holds that data. */
|
||||||
for (java.util.Iterator i = t.iterator(); i.hasNext();) {
|
for (final Object e : t) {
|
||||||
Object e = i.next();
|
|
||||||
assertTrue("Error: m and t differ on a key (" + e + ") after insertion (iterating on t)", s.contains(e));
|
assertTrue("Error: m and t differ on a key (" + e + ") after insertion (iterating on t)", s.contains(e));
|
||||||
}
|
}
|
||||||
/* Now we check that m actually holds that data, but iterating on m. */
|
/* Now we check that m actually holds that data, but iterating on m. */
|
||||||
c = 0;
|
c = 0;
|
||||||
for (java.util.Iterator i = s.iterator(); i.hasNext();) {
|
for (final java.util.Iterator i = s.iterator(); i.hasNext();) {
|
||||||
Object e = i.next();
|
final Object e = i.next();
|
||||||
c++;
|
c++;
|
||||||
assertTrue("Error: m and t differ on a key (" + e + ") after insertion (iterating on m)", t.contains(e));
|
assertTrue("Error: m and t differ on a key (" + e + ") after insertion (iterating on m)", t.contains(e));
|
||||||
}
|
}
|
||||||
|
@ -112,7 +111,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
* use the polymorphic method.
|
* use the polymorphic method.
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
int T = genKey();
|
final int T = genKey();
|
||||||
assertTrue("Error: divergence in keys between t and m (polymorphic method)", s.contains(T) == t.contains((Integer.valueOf(T))));
|
assertTrue("Error: divergence in keys between t and m (polymorphic method)", s.contains(T) == t.contains((Integer.valueOf(T))));
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -120,7 +119,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
* m we use the standard method.
|
* m we use the standard method.
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
int T = genKey();
|
final int T = genKey();
|
||||||
assertTrue("Error: divergence between t and m (standard method)", s.contains((Integer.valueOf(T))) == t.contains((Integer.valueOf(T))));
|
assertTrue("Error: divergence between t and m (standard method)", s.contains((Integer.valueOf(T))) == t.contains((Integer.valueOf(T))));
|
||||||
}
|
}
|
||||||
/* Now we put and remove random data in m and t, checking that the result is the same. */
|
/* Now we put and remove random data in m and t, checking that the result is the same. */
|
||||||
|
@ -133,30 +132,29 @@ public class IntLinkedOpenHashSetTest {
|
||||||
assertTrue("Error: !m.equals(t) after removal", s.equals(t));
|
assertTrue("Error: !m.equals(t) after removal", s.equals(t));
|
||||||
assertTrue("Error: !t.equals(m) after removal", t.equals(s));
|
assertTrue("Error: !t.equals(m) after removal", t.equals(s));
|
||||||
/* Now we check that m actually holds that data. */
|
/* Now we check that m actually holds that data. */
|
||||||
for (java.util.Iterator i = t.iterator(); i.hasNext();) {
|
for (final Object e : t) {
|
||||||
Object e = i.next();
|
|
||||||
assertTrue("Error: m and t differ on a key (" + e + ") after removal (iterating on t)", s.contains(e));
|
assertTrue("Error: m and t differ on a key (" + e + ") after removal (iterating on t)", s.contains(e));
|
||||||
}
|
}
|
||||||
/* Now we check that m actually holds that data, but iterating on m. */
|
/* Now we check that m actually holds that data, but iterating on m. */
|
||||||
for (java.util.Iterator i = s.iterator(); i.hasNext();) {
|
for (final java.util.Iterator i = s.iterator(); i.hasNext();) {
|
||||||
Object e = i.next();
|
final Object e = i.next();
|
||||||
assertTrue("Error: m and t differ on a key (" + e + ") after removal (iterating on m)", t.contains(e));
|
assertTrue("Error: m and t differ on a key (" + e + ") after removal (iterating on m)", t.contains(e));
|
||||||
}
|
}
|
||||||
/* Now we make m into an array, make it again a set and check it is OK. */
|
/* Now we make m into an array, make it again a set and check it is OK. */
|
||||||
int a[] = s.toIntArray();
|
final int a[] = s.toIntArray();
|
||||||
assertEquals("Error: toArray() output (or array-based constructor) is not OK", new IntLinkedOpenHashSet(a), s);
|
assertEquals("Error: toArray() output (or array-based constructor) is not OK", new IntLinkedOpenHashSet(a), s);
|
||||||
/* Now we check cloning. */
|
/* Now we check cloning. */
|
||||||
assertTrue("Error: m does not equal m.clone()", s.equals(s.clone()));
|
assertTrue("Error: m does not equal m.clone()", s.equals(s.clone()));
|
||||||
assertTrue("Error: m.clone() does not equal m", s.clone().equals(s));
|
assertTrue("Error: m.clone() does not equal m", s.clone().equals(s));
|
||||||
int h = s.hashCode();
|
final int h = s.hashCode();
|
||||||
/* Now we save and read m. */
|
/* Now we save and read m. */
|
||||||
java.io.File ff = new java.io.File("it.unimi.dsi.fastutil.test.junit." + s.getClass().getSimpleName() + "." + n);
|
final java.io.File ff = new java.io.File("it.unimi.dsi.fastutil.test.junit." + s.getClass().getSimpleName() + "." + n);
|
||||||
java.io.OutputStream os = new java.io.FileOutputStream(ff);
|
final java.io.OutputStream os = new java.io.FileOutputStream(ff);
|
||||||
java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(os);
|
final java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(os);
|
||||||
oos.writeObject(s);
|
oos.writeObject(s);
|
||||||
oos.close();
|
oos.close();
|
||||||
java.io.InputStream is = new java.io.FileInputStream(ff);
|
final java.io.InputStream is = new java.io.FileInputStream(ff);
|
||||||
java.io.ObjectInputStream ois = new java.io.ObjectInputStream(is);
|
final java.io.ObjectInputStream ois = new java.io.ObjectInputStream(is);
|
||||||
s = (IntLinkedOpenHashSet)ois.readObject();
|
s = (IntLinkedOpenHashSet)ois.readObject();
|
||||||
ois.close();
|
ois.close();
|
||||||
ff.delete();
|
ff.delete();
|
||||||
|
@ -164,8 +162,8 @@ public class IntLinkedOpenHashSetTest {
|
||||||
|
|
||||||
assertEquals("Error: clone()", s, s.clone());
|
assertEquals("Error: clone()", s, s.clone());
|
||||||
/* Now we check that m actually holds that data, but iterating on m. */
|
/* Now we check that m actually holds that data, but iterating on m. */
|
||||||
for (java.util.Iterator i = s.iterator(); i.hasNext();) {
|
for (final java.util.Iterator i = s.iterator(); i.hasNext();) {
|
||||||
Object e = i.next();
|
final Object e = i.next();
|
||||||
assertTrue("Error: m and t differ on a key (" + e + ") after save/read", t.contains(e));
|
assertTrue("Error: m and t differ on a key (" + e + ") after save/read", t.contains(e));
|
||||||
}
|
}
|
||||||
/* Now we put and remove random data in m and t, checking that the result is the same. */
|
/* Now we put and remove random data in m and t, checking that the result is the same. */
|
||||||
|
@ -243,7 +241,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
assertTrue("Error: ! m.equals(t) after iteration", s.equals(t));
|
assertTrue("Error: ! m.equals(t) after iteration", s.equals(t));
|
||||||
assertTrue("Error: ! t.equals(m) after iteration", t.equals(s));
|
assertTrue("Error: ! t.equals(m) after iteration", t.equals(s));
|
||||||
/* Now we take out of m everything, and check that it is empty. */
|
/* Now we take out of m everything, and check that it is empty. */
|
||||||
for (java.util.Iterator i = s.iterator(); i.hasNext();) {
|
for (final java.util.Iterator i = s.iterator(); i.hasNext();) {
|
||||||
i.next();
|
i.next();
|
||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
|
@ -291,7 +289,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Test
|
@Test
|
||||||
public void testAdd() {
|
public void testAdd() {
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
assertTrue(s.add(0));
|
assertTrue(s.add(0));
|
||||||
assertTrue(s.contains(0));
|
assertTrue(s.contains(0));
|
||||||
assertFalse(s.contains(1));
|
assertFalse(s.contains(1));
|
||||||
|
@ -302,7 +300,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemove() {
|
public void testRemove() {
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
||||||
for(int i = 0; i < 100; i++) assertFalse(s.remove(100 + i));
|
for(int i = 0; i < 100; i++) assertFalse(s.remove(100 + i));
|
||||||
assertEquals(0, s.firstInt());
|
assertEquals(0, s.firstInt());
|
||||||
|
@ -316,7 +314,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
for(int i = -1; i <= 1; i++) assertTrue(s.add(i));
|
for(int i = -1; i <= 1; i++) assertTrue(s.add(i));
|
||||||
assertTrue(s.remove(0));
|
assertTrue(s.remove(0));
|
||||||
IntListIterator iterator = s.iterator();
|
IntListIterator iterator = s.iterator();
|
||||||
IntOpenHashSet z = new IntOpenHashSet();
|
final IntOpenHashSet z = new IntOpenHashSet();
|
||||||
z.add(iterator.nextInt());
|
z.add(iterator.nextInt());
|
||||||
z.add(iterator.nextInt());
|
z.add(iterator.nextInt());
|
||||||
assertFalse(iterator.hasNext());
|
assertFalse(iterator.hasNext());
|
||||||
|
@ -367,7 +365,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIterator() {
|
public void testIterator() {
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
||||||
assertEquals(0, s.firstInt());
|
assertEquals(0, s.firstInt());
|
||||||
|
|
||||||
|
@ -424,14 +422,14 @@ public class IntLinkedOpenHashSetTest {
|
||||||
|
|
||||||
@Test(expected=NoSuchElementException.class)
|
@Test(expected=NoSuchElementException.class)
|
||||||
public void testIteratorMissingElement() {
|
public void testIteratorMissingElement() {
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
||||||
s.iterator(1000);
|
s.iterator(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPutAndMove() {
|
public void testPutAndMove() {
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
for(int i = 0; i < 100; i++) assertTrue(s.addAndMoveToFirst(i));
|
for(int i = 0; i < 100; i++) assertTrue(s.addAndMoveToFirst(i));
|
||||||
s.clear();
|
s.clear();
|
||||||
for(int i = 0; i < 100; i++) assertTrue(s.addAndMoveToLast(i));
|
for(int i = 0; i < 100; i++) assertTrue(s.addAndMoveToLast(i));
|
||||||
|
@ -459,7 +457,7 @@ public class IntLinkedOpenHashSetTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveFirstLast() {
|
public void testRemoveFirstLast() {
|
||||||
IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet(Hash.DEFAULT_INITIAL_SIZE);
|
||||||
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
for(int i = 0; i < 100; i++) assertTrue(s.add(i));
|
||||||
assertEquals(0, s.removeFirstInt());
|
assertEquals(0, s.removeFirstInt());
|
||||||
assertEquals(1, s.removeFirstInt());
|
assertEquals(1, s.removeFirstInt());
|
||||||
|
@ -502,19 +500,19 @@ public class IntLinkedOpenHashSetTest {
|
||||||
@Test
|
@Test
|
||||||
public void testToSet() {
|
public void testToSet() {
|
||||||
final IntLinkedOpenHashSet baseSet = IntLinkedOpenHashSet.of(2, 380, 1297);
|
final IntLinkedOpenHashSet baseSet = IntLinkedOpenHashSet.of(2, 380, 1297);
|
||||||
IntLinkedOpenHashSet transformed = IntLinkedOpenHashSet.toSet(baseSet.intStream().map(i -> i + 40));
|
final IntLinkedOpenHashSet transformed = IntLinkedOpenHashSet.toSet(baseSet.intStream().map(i -> i + 40));
|
||||||
assertEquals(IntLinkedOpenHashSet.of(42, 420, 1337), transformed);
|
assertEquals(IntLinkedOpenHashSet.of(42, 420, 1337), transformed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSpliteratorTrySplit() {
|
public void testSpliteratorTrySplit() {
|
||||||
final IntLinkedOpenHashSet baseSet = IntLinkedOpenHashSet.of(0, 1, 2, 3, 72, 5, 6);
|
final IntLinkedOpenHashSet baseSet = IntLinkedOpenHashSet.of(0, 1, 2, 3, 72, 5, 6);
|
||||||
IntSpliterator spliterator1 = baseSet.spliterator();
|
final IntSpliterator spliterator1 = baseSet.spliterator();
|
||||||
assertEquals(baseSet.size(), spliterator1.getExactSizeIfKnown());
|
assertEquals(baseSet.size(), spliterator1.getExactSizeIfKnown());
|
||||||
IntSpliterator spliterator2 = spliterator1.trySplit();
|
final IntSpliterator spliterator2 = spliterator1.trySplit();
|
||||||
// No assurance of where we split, but where ever it is it should be a perfect split.
|
// No assurance of where we split, but where ever it is it should be a perfect split.
|
||||||
java.util.stream.IntStream stream1 = java.util.stream.StreamSupport.intStream(spliterator1, false);
|
final java.util.stream.IntStream stream1 = java.util.stream.StreamSupport.intStream(spliterator1, false);
|
||||||
java.util.stream.IntStream stream2 = java.util.stream.StreamSupport.intStream(spliterator2, false);
|
final java.util.stream.IntStream stream2 = java.util.stream.StreamSupport.intStream(spliterator2, false);
|
||||||
|
|
||||||
final IntLinkedOpenHashSet subSet1 = IntLinkedOpenHashSet.toSet(stream1);
|
final IntLinkedOpenHashSet subSet1 = IntLinkedOpenHashSet.toSet(stream1);
|
||||||
// Intentionally collecting to a list for this second one.
|
// Intentionally collecting to a list for this second one.
|
||||||
|
@ -530,4 +528,12 @@ public class IntLinkedOpenHashSetTest {
|
||||||
public void testLegacyMainMethodTests() throws Exception {
|
public void testLegacyMainMethodTests() throws Exception {
|
||||||
MainRunner.callMainIfExists(IntLinkedOpenHashSet.class, "test", /*num=*/"500", /*loadFactor=*/"0.75", /*seed=*/"3832474");
|
MainRunner.callMainIfExists(IntLinkedOpenHashSet.class, "test", /*num=*/"500", /*loadFactor=*/"0.75", /*seed=*/"3832474");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveLast() {
|
||||||
|
final IntLinkedOpenHashSet s = new IntLinkedOpenHashSet();
|
||||||
|
s.add(0);
|
||||||
|
s.removeLastInt();
|
||||||
|
assertFalse(s.iterator().hasNext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue