public ConcurrentLongHashSet keysLongHashSet() { ConcurrentLongHashSet concurrentLongHashSet = new ConcurrentLongHashSet(size()); forEach((key, value) -> concurrentLongHashSet.add(key)); return concurrentLongHashSet; }
/** * @return a new list of all keys (makes a copy) */ public Set<Long> items() { Set<Long> items = new HashSet<>(); forEach(items::add); return items; }
/** * Remove an existing entry if found * * @param item * @return true if removed or false if item was not present */ public boolean remove(long item) { checkBiggerEqualZero(item); long h = hash(item); return getSection(h).remove(item, (int) h); }
private static void insertKeyValueNoLock(long[] table, int capacity, long item) { int bucket = signSafeMod(hash(item), capacity); while (true) { long storedKey = table[bucket]; if (storedKey == EmptyItem) { // The bucket is empty, so we can use it table[bucket] = item; return; } bucket = (bucket + 1) & (table.length - 1); } } }
@Test public void testHashConflictWithDeletion() { final int Buckets = 16; ConcurrentLongHashSet set = new ConcurrentLongHashSet(Buckets, 1); // Pick 2 keys that fall into the same bucket long key1 = 1; long key2 = 27; int bucket1 = ConcurrentLongHashSet.signSafeMod(ConcurrentLongHashSet.hash(key1), Buckets); int bucket2 = ConcurrentLongHashSet.signSafeMod(ConcurrentLongHashSet.hash(key2), Buckets); assertEquals(bucket1, bucket2); assertTrue(set.add(key1)); assertTrue(set.add(key2)); assertEquals(set.size(), 2); assertTrue(set.remove(key1)); assertEquals(set.size(), 1); assertTrue(set.add(key1)); assertEquals(set.size(), 2); assertTrue(set.remove(key1)); assertEquals(set.size(), 1); assertFalse(set.add(key2)); assertTrue(set.contains(key2)); assertEquals(set.size(), 1); assertTrue(set.remove(key2)); assertTrue(set.isEmpty()); }
boolean contains(long item, int hash) { long stamp = tryOptimisticRead(); boolean acquiredLock = false; int bucket = signSafeMod(hash, capacity); acquiredLock = true; bucket = signSafeMod(hash, capacity); storedItem = table[bucket];
@Test public void testIteration() { ConcurrentLongHashSet set = new ConcurrentLongHashSet(); assertEquals(set.items(), Collections.emptySet()); set.add(0L); assertEquals(set.items(), new HashSet<>(Arrays.asList(0L))); set.remove(0L); assertEquals(set.items(), Collections.emptySet()); set.add(0L); set.add(1L); set.add(2L); List<Long> values = new ArrayList<>(set.items()); Collections.sort(values); assertEquals(values, Arrays.asList(0L, 1L, 2L)); set.clear(); assertTrue(set.isEmpty()); }
@Test public void simpleInsertions() { ConcurrentLongHashSet set = new ConcurrentLongHashSet(16); assertTrue(set.isEmpty()); assertTrue(set.add(1)); assertFalse(set.isEmpty()); assertTrue(set.add(2)); assertTrue(set.add(3)); assertEquals(set.size(), 3); assertTrue(set.contains(1)); assertEquals(set.size(), 3); assertTrue(set.remove(1)); assertEquals(set.size(), 2); assertFalse(set.contains(1)); assertFalse(set.contains(5)); assertEquals(set.size(), 2); assertTrue(set.add(1)); assertEquals(set.size(), 3); assertFalse(set.add(1)); assertEquals(set.size(), 3); }
protected void addToRecordsSnaptshot(final long id) { recordsSnapshot.add(id); }
Section(int capacity) { this.capacity = alignToPowerOfTwo(capacity); this.table = new long[this.capacity]; this.size = 0; this.usedBuckets = 0; this.resizeThreshold = (int) (this.capacity * SetFillFactor); Arrays.fill(table, EmptyItem); }
private final ConcurrentLongHashSet pendingRecords = new ConcurrentLongHashSet();
private static void insertKeyValueNoLock(long[] table, int capacity, long item) { int bucket = signSafeMod(hash(item), capacity); while (true) { long storedKey = table[bucket]; if (storedKey == EmptyItem) { // The bucket is empty, so we can use it table[bucket] = item; return; } bucket = (bucket + 1) & (table.length - 1); } } }
@SuppressWarnings("NonAtomicVolatileUpdate") private boolean remove(long item, int hash) { long stamp = writeLock(); int bucket = signSafeMod(hash, capacity); try { while (true) { long storedItem = table[bucket]; if (item == storedItem) { --size; cleanBucket(bucket); return true; } else if (storedItem == EmptyItem) { // Key wasn't found return false; } bucket = (bucket + 1) & (table.length - 1); } } finally { unlockWrite(stamp); } }
@Test public void testRehashingWithDeletes() { int n = 16; ConcurrentLongHashSet set = new ConcurrentLongHashSet(n / 2, 1); assertEquals(set.capacity(), n); assertEquals(set.size(), 0); for (int i = 0; i < n / 2; i++) { set.add(i); } for (int i = 0; i < n / 2; i++) { set.remove(i); } for (int i = n; i < (2 * n); i++) { set.add(i); } assertEquals(set.capacity(), 2 * n); assertEquals(set.size(), n); }
protected void addToRecordsSnaptshot(final long id) { recordsSnapshot.add(id); }
Section(int capacity) { this.capacity = alignToPowerOfTwo(capacity); this.table = new long[this.capacity]; this.size = 0; this.usedBuckets = 0; this.resizeThreshold = (int) (this.capacity * SetFillFactor); Arrays.fill(table, EmptyItem); }
private final ConcurrentLongHashSet pendingRecords = new ConcurrentLongHashSet();
public boolean contains(long item) { checkBiggerEqualZero(item); long h = hash(item); return getSection(h).contains(item, (int) h); }