add Sparse2DLongArray

This commit is contained in:
2019-12-26 15:44:58 +01:00
parent ec7a03f068
commit c6f5a3d2fe
7 changed files with 940 additions and 0 deletions

View File

@@ -0,0 +1,250 @@
package org.lucares.collections;
import java.util.Random;
import java.util.function.Supplier;
import java.util.stream.LongStream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class LongObjHashMapTest {
private static final class LongSupplier implements Supplier<Long>{
private final Long value ;
public LongSupplier(Long value) {
this.value = value;
}
@Override
public Long get() {
return value;
}
}
@Test
public void testPutRemove() {
putGetRemove(1);
}
@Test
public void testNullValue() {
putGetRemove(0);
}
private void putGetRemove(final long key) {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final long valueA = 2L;
final long valueB = 3L;
// value does not exist
Assertions.assertFalse(map.containsKey(key));
Assertions.assertEquals(0, map.size());
// add value and check it is in the map
map.put(key, valueA);
Assertions.assertTrue(map.containsKey(key));
Assertions.assertEquals(valueA, map.get(key));
Assertions.assertEquals(1, map.size());
// overwrite value
map.put(key, valueB);
Assertions.assertEquals(valueB, map.get(key));
Assertions.assertEquals(1, map.size());
// remove value and check it is gone
map.remove(key);
Assertions.assertFalse(map.containsKey(key));
Assertions.assertEquals(0, map.size());
}
@Test
public void testComputeZeroKey() {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final long key = 1;
map.compute(key, new LongSupplier(6L), (k,l) -> l + 1);
Assertions.assertEquals(7, map.get(key), "initialValueIfAbsent is used when there is no mapping for the key");
map.compute(key, new LongSupplier(6L), (k,l) -> l + 1);
Assertions.assertEquals(8, map.get(key), "update function is called when 'zeroKey' is set");
}
@Test
public void testCompute() {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final long key = 1;
map.compute(key, new LongSupplier(6L), (k,l) -> l + 1);
Assertions.assertEquals(7, map.get(key), "initialValueIfAbsent is used when there is no mapping for the key");
map.compute(key, new LongSupplier(6L), (k,l) -> l + 1);
Assertions.assertEquals(8, map.get(key), "update function is called when key is set");
}
@Test
public void testGrowMap() {
final LongObjHashMap<Long> map = new LongObjHashMap<>(4, 0.75);
final int numEntries = 12;
final Random rand = new Random(12345);
final LongList entries = LongList.of(LongStream.generate(rand::nextLong).limit(numEntries).toArray());
entries.stream().forEachOrdered(l -> {
map.put(l, l);
});
entries.stream().forEachOrdered(l -> {
Assertions.assertEquals(l, map.get(l));
});
Assertions.assertEquals(16, map.getCapacity(), "capacity after adding 12 entries must be a the smallest number "
+ "that satisfies initialCapacity * 2^n >= entries/fillFactor");
}
@Test
public void testMultipleValuesOnSamePosition() {
final int initialCapacity = 20;
final LongObjHashMap<Long> map = new LongObjHashMap<>(initialCapacity, 0.75);
// find to values that yield the same 'spread' (position in the table)
final LongList keysWithSameSpread = findKeysWithSameSpread(map);
Assertions.assertTrue(keysWithSameSpread.size() > 5);
keysWithSameSpread.stream().forEach(l -> map.put(l, l));
Assertions.assertEquals(keysWithSameSpread.size(), map.size());
keysWithSameSpread.stream().forEach(l -> Assertions.assertEquals(l, map.get(l)));
}
@Test
public void testForEach() {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final Random rand = new Random(6789);
final LongList entries = LongList.of(LongStream.generate(rand::nextLong).limit(15).toArray());
entries.stream().forEachOrdered(l -> {
map.put(l, 2 * l);
});
map.forEach((k, v) -> {
Assertions.assertEquals(k * 2, v, "value is key*2");
Assertions.assertTrue(entries.indexOf(k) >= 0, "value " + k + " in entries: " + entries);
});
}
@Test
public void testForEachOrdered() {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final Random rand = new Random(6789);
final LongList entries = LongList.of(LongStream.generate(rand::nextLong).limit(15).toArray());
entries.stream().forEachOrdered(l -> {
map.put(l, 2 * l);
});
final LongList actualOrderOfKeys = new LongList();
map.forEachOrdered((k, v) -> {
Assertions.assertEquals(k * 2, v, "value is key*2");
Assertions.assertTrue(entries.indexOf(k) >= 0, "value " + k + " in entries: " + entries);
actualOrderOfKeys.add(k);
});
Assertions.assertTrue(actualOrderOfKeys.isSorted(), "keys are sorted");
Assertions.assertEquals(LongList.intersection(actualOrderOfKeys, entries).size(), entries.size(),
"all keys were visited");
final LongList additionalKeys = new LongList(actualOrderOfKeys);
additionalKeys.removeAll(entries);
Assertions.assertEquals(additionalKeys, LongList.of(), "no additional keys were visited");
}
@Test
public void testForEachOrderedOnlyNegativeValues() {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final LongList entries = LongList.of(LongStream.range(-20, -5).toArray());
entries.stream().forEachOrdered(l -> {
map.put(l, 2 * l);
});
final LongList actualOrderOfKeys = new LongList();
map.forEachOrdered((k, v) -> {
Assertions.assertEquals(k * 2, v, "value is key*2");
Assertions.assertTrue(entries.indexOf(k) >= 0, "value " + k + " in entries: " + entries);
actualOrderOfKeys.add(k);
});
Assertions.assertTrue(actualOrderOfKeys.isSorted(), "keys are sorted");
Assertions.assertEquals(LongList.intersection(actualOrderOfKeys, entries).size(), entries.size(),
"all keys were visited");
final LongList additionalKeys = new LongList(actualOrderOfKeys);
additionalKeys.removeAll(entries);
Assertions.assertEquals(additionalKeys, LongList.of(), "no additional keys were visited");
}
@Test
public void testForEachOrderedOnlyNegativeValues2() {
final LongObjHashMap<Long> map = new LongObjHashMap<>();
final LongList entries = LongList.of(LongStream.range(-20, -5).toArray());
entries.stream().forEachOrdered(l -> {
map.put(l, 2 * l);
});
final LongList actualOrderOfKeys = new LongList();
map.forEachOrdered((k, v) -> {
Assertions.assertEquals(k * 2, v, "value is key*2");
Assertions.assertTrue(entries.indexOf(k) >= 0, "value " + k + " in entries: " + entries);
actualOrderOfKeys.add(k);
});
Assertions.assertTrue(actualOrderOfKeys.isSorted(), "keys are sorted");
}
@Test
public void testFindPositionOfFirstPositiveKey() {
Assertions.assertEquals(-1, LongObjHashMap.findPosOfFirstPositiveKey(new long[] {}));
Assertions.assertEquals(-1, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0 }));
Assertions.assertEquals(0, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 1 }));
Assertions.assertEquals(1, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 1 }));
Assertions.assertEquals(0, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 1, 1 }));
Assertions.assertEquals(2, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, 0, 1 }));
Assertions.assertEquals(0, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 1, 1, 1, 1, 1, 1, 1, 1, 1 }));
Assertions.assertEquals(0, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 1, 1, 1, 1, 1, 1, 1, 1 }));
Assertions.assertEquals(4,
LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, -1, -1, -1, 1, 1, 1, 1, 1 }));
Assertions.assertEquals(4,
LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, -1, -1, -1, 1, 1, 1, 1 }));
Assertions.assertEquals(3,
LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, -1, -1, 1, 1, 1, 1, 1, 1 }));
Assertions.assertEquals(3, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, -1, -1, 1, 1, 1, 1, 1 }));
Assertions.assertEquals(-1, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 0 }));
Assertions.assertEquals(-1, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 0, 0 }));
Assertions.assertEquals(4, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 1, 1, 1, 1 }));
Assertions.assertEquals(5, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 0, 1, 1, 1 }));
Assertions.assertEquals(6, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 0, 0, 1, 1 }));
Assertions.assertEquals(4, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 1, 1, 1 }));
Assertions.assertEquals(5, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 0, 1, 1 }));
Assertions.assertEquals(6, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { 0, 0, 0, 0, 0, 0, 1 }));
Assertions.assertEquals(4, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, 0, 0, 0, 1, 1, 1 }));
Assertions.assertEquals(5, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, 0, 0, 0, 0, 1, 1 }));
Assertions.assertEquals(6, LongObjHashMap.findPosOfFirstPositiveKey(new long[] { -1, 0, 0, 0, 0, 0, 1 }));
}
private LongList findKeysWithSameSpread(final LongObjHashMap<?> map) {
final LongList result = new LongList();
final int spread = map.spread(1);
result.add(1);
for (long l = 2; l < 10000; l++) {
final int s = map.spread(l);
if (s == spread) {
result.add(l);
if (result.size() > 10) {
break;
}
}
}
return result;
}
}