All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rx.internal.util.OpenHashSet Maven / Gradle / Ivy

There is a newer version: 1.3.8
Show newest version
/**
 * Copyright 2014 Netflix, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Modified from http://www.javacodegeeks.com/2013/08/simple-and-lightweight-pool-implementation.html
 */

package rx.internal.util;

import java.util.Arrays;

import rx.functions.Action1;
import rx.internal.util.unsafe.Pow2;

/*
 * Inspired by fastutils' OpenHashSet implementation at
 * https://github.com/vigna/fastutil/blob/master/drv/OpenHashSet.drv
 */

/**
 * A simple open hash set with add, remove and clear capabilities only.
 * 

Doesn't support nor checks for {@code null}s. * * @param the element type */ public final class OpenHashSet { final float loadFactor; int mask; int size; int maxSize; T[] keys; private static final int INT_PHI = 0x9E3779B9; public OpenHashSet() { this(16, 0.75f); } /** * Creates an OpenHashSet with the initial capacity and load factor of 0.75f. * @param capacity the initial capacity */ public OpenHashSet(int capacity) { this(capacity, 0.75f); } @SuppressWarnings("unchecked") public OpenHashSet(int capacity, float loadFactor) { this.loadFactor = loadFactor; int c = Pow2.roundToPowerOfTwo(capacity); this.mask = c - 1; this.maxSize = (int)(loadFactor * c); this.keys = (T[])new Object[c]; } public boolean add(T value) { final T[] a = keys; final int m = mask; int pos = mix(value.hashCode()) & m; T curr = a[pos]; if (curr != null) { if (curr.equals(value)) { return false; } for (;;) { pos = (pos + 1) & m; curr = a[pos]; if (curr == null) { break; } if (curr.equals(value)) { return false; } } } a[pos] = value; if (++size >= maxSize) { rehash(); } return true; } public boolean remove(T value) { T[] a = keys; int m = mask; int pos = mix(value.hashCode()) & m; T curr = a[pos]; if (curr == null) { return false; } if (curr.equals(value)) { return removeEntry(pos, a, m); } for (;;) { pos = (pos + 1) & m; curr = a[pos]; if (curr == null) { return false; } if (curr.equals(value)) { return removeEntry(pos, a, m); } } } boolean removeEntry(int pos, T[] a, int m) { size--; int last; int slot; T curr; for (;;) { last = pos; pos = (pos + 1) & m; for (;;) { curr = a[pos]; if (curr == null) { a[last] = null; return true; } slot = mix(curr.hashCode()) & m; if (last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos) { break; } pos = (pos + 1) & m; } a[last] = curr; } } public void clear(Action1 clearAction) { if (size == 0) { return; } T[] a = keys; int len = a.length; for (int i = 0; i < len; i++) { T e = a[i]; if (e != null) { clearAction.call(e); } } Arrays.fill(a, null); size = 0; } @SuppressWarnings("unchecked") public void terminate() { size = 0; keys = (T[])new Object[0]; } @SuppressWarnings("unchecked") void rehash() { T[] a = keys; int i = a.length; int newCap = i << 1; int m = newCap - 1; T[] b = (T[])new Object[newCap]; for (int j = size; j-- != 0; ) { while (a[--i] == null); // NOPMD int pos = mix(a[i].hashCode()) & m; if (b[pos] != null) { for (;;) { pos = (pos + 1) & m; if (b[pos] == null) { break; } } } b[pos] = a[i]; } this.mask = m; this.maxSize = (int)(newCap * loadFactor); this.keys = b; } static int mix(int x) { final int h = x * INT_PHI; return h ^ (h >>> 16); } public boolean isEmpty() { return size == 0; } /** * Returns the raw array of values of this set, watch out for null entires. * @return the raw array of values of this set */ public T[] values() { return keys; // NOPMD } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy