
org.zoodb.jdo.internal.util.ObjectIdentitySet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of parent Show documentation
Show all versions of parent Show documentation
ZooDB Java JDO Object Database.
The newest version!
/*
* Copyright 2009-2013 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see .
*
* See the README and COPYING files for further information.
*/
package org.zoodb.jdo.internal.util;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* This class is an implementation of the Set interface. To check object
* equality, it uses '==' instead of 'equals()'.
*
* @param
* @author Tilmann Zaeschke
*/
public final class ObjectIdentitySet implements Set
{
private ObjectIdentitySetEntry[] table;
private int count;
private int threshold;
private static final float LOAD_FACTOR = 0.75f;
private static final int INITIAL_CAPACITY = 127;
/**
* Create a new ObjectIdentitySet.
*/
public ObjectIdentitySet () {
this (INITIAL_CAPACITY);
}
@SuppressWarnings("unchecked")
public ObjectIdentitySet (int initial_capacity) {
if (initial_capacity > INITIAL_CAPACITY) {
//First get a good number: (2^n)-1 > initial_capacity
//Ideally, n would be a prime, but that's getting too
//difficult here.
int p = 1;
while (initial_capacity > 1) {
initial_capacity = initial_capacity >> 2;
p++;
}
if (p%2 == 0) {
p++;
}
initial_capacity = (int) Math.pow(2, p) - 1;
} else {
//Go for minimal feasible size (expecting resizing)
initial_capacity = INITIAL_CAPACITY;
}
int initial_size = (int) (initial_capacity / LOAD_FACTOR);
table = new ObjectIdentitySetEntry [initial_size];
count = 0;
threshold = initial_capacity;
}
/**
* @param object
* @return Returns true if the object was added, otherwise
* false.
* @see java.util.Set#add(java.lang.Object)
*/
public final boolean add (E object) {
int hash = System.identityHashCode (object);
int index = (hash & 0x7FFFFFFF) % table.length;
ObjectIdentitySetEntry head = table [index];
for (ObjectIdentitySetEntry e = head; e != null; e = e.next) {
if (object == e.object)
return false;
}
table [index] = new ObjectIdentitySetEntry (object, head);
count++;
if (count >= threshold)
rehash (count * 2 + 1);
return true;
}
final void add (E[] objects) {
for (E obj: objects) {
add (obj);
}
}
/**
* @see java.util.Set#contains(java.lang.Object)
*/
public final boolean contains (Object object) {
int hash = System.identityHashCode (object);
int index = (hash & 0x7FFFFFFF) % table.length;
ObjectIdentitySetEntry e;
for (e = table [index]; e != null; e = e.next) {
if (object == e.object)
return true;
}
return false;
}
@SuppressWarnings("unchecked")
final void rehash (int new_length) {
ObjectIdentitySetEntry[] old_table = table;
int old_length = old_table.length;
//int new_length = old_length * 2 + 1;
ObjectIdentitySetEntry[] new_table =
new ObjectIdentitySetEntry [new_length];
for (int i = 0; i < old_length; i++) {
ObjectIdentitySetEntry next;
ObjectIdentitySetEntry e;
for (e = old_table [i]; e != null; e = next) {
int hash = System.identityHashCode (e.object);
int new_index = ((hash & 0x7FFFFFFF) % new_length);
next = e.next;
e.next = new_table [new_index];
new_table [new_index] = e;
}
}
table = new_table;
threshold = (int) (new_length * LOAD_FACTOR);
}
/**
* @see java.util.Set#size()
*/
public final int size() {
return count;
}
/**
* @see java.util.Set#clear()
*/
@SuppressWarnings("unchecked")
public final void clear() {
threshold = INITIAL_CAPACITY;
count = 0;
table = new ObjectIdentitySetEntry [(int) (threshold / LOAD_FACTOR)];
}
/**
* @see java.util.Set#isEmpty()
*/
public final boolean isEmpty() {
return count == 0;
}
/**
* @see java.util.Set#toArray()
*/
public final Object[] toArray() {
Object[] a = new Object[count];
int j = 0;
for (Iterator i = this.iterator(); i.hasNext(); ) {
a[j++] = i.next();
}
return a;
}
/**
* @see java.util.Set#remove(java.lang.Object)
*/
public final boolean remove(Object obj) {
int hash = System.identityHashCode (obj);
int index = (hash & 0x7FFFFFFF) % table.length;
ObjectIdentitySetEntry e;
ObjectIdentitySetEntry prev = null;
for (e = table [index]; e != null; e = e.next) {
if (obj == e.object) {
//delete it
if (prev == null) {
//first element
table [index] = e.next;
} else {
prev.next = e.next;
}
count--;
// rehash if < 25% filled and size > 127
if (count < threshold*(1-LOAD_FACTOR)
&& count > INITIAL_CAPACITY)
rehash (count / 2 + 1);
return true;
}
prev = e;
}
return false;
}
/**
* @see java.util.Set#addAll(java.util.Collection)
*/
public final boolean addAll(Collection extends E> c) {
boolean ret = false;
for (E o: c) {
ret |= add(o);
}
return ret;
}
/**
* Add all elements of in the enumeration
* @param en
*/
public final void addAll(Enumeration en) {
while (en.hasMoreElements()) {
add(en.nextElement());
}
}
/**
* @see java.util.Set#containsAll(java.util.Collection)
*/
public final boolean containsAll(Collection> c) {
if (c == null) {
throw new NullPointerException();
}
throw new UnsupportedOperationException();
}
/**
* @see java.util.Set#removeAll(java.util.Collection)
*/
public final boolean removeAll(Collection> c) {
if (c == null) {
throw new NullPointerException();
}
boolean hasChanged = false;
for (Object o: c) {
if (remove(o)) hasChanged = true;
}
return hasChanged;
}
/**
* @see java.util.Set#retainAll(java.util.Collection)
*/
public final boolean retainAll(Collection> c) {
if (c == null) {
throw new NullPointerException();
}
throw new UnsupportedOperationException();
}
/**
* @see java.util.Set#iterator()
*/
public final Iterator iterator() {
return new ObjectIdentitySetIterator();
}
/**
* @param a
* @param
* @return Array representation of this container
* @see java.util.Set#toArray(Object[])
*/
public final T[] toArray(T[] a) {
if (a == null) {
throw new NullPointerException();
}
throw new UnsupportedOperationException();
}
/**
* @see java.lang.Object#toString()
*/
public final String toString() {
StringBuffer buf = new StringBuffer();
buf.append("ObjectIdentitySet(" + count + "): ");
for (Iterator i = this.iterator(); i.hasNext(); ) {
buf.append(i.next() + "; ");
}
return buf.toString();
}
private final static class ObjectIdentitySetEntry {
private final T object;
private ObjectIdentitySetEntry next;
ObjectIdentitySetEntry (T object1, ObjectIdentitySetEntry next1) {
object = object1;
next = next1;
}
}
private final class ObjectIdentitySetIterator implements Iterator {
private int pos = 0;
private ObjectIdentitySetEntry next = null;
/**
* @see java.util.Iterator#remove()
*/
public final void remove() {
throw new UnsupportedOperationException();
}
/**
* @see java.util.Iterator#hasNext()
*/
public final boolean hasNext() {
if (next == null) {
for( ; pos < table.length; pos++) {
if (table[pos] != null) {
next = table[pos];
pos++;
return true;
}
}
return false;
}
return true;
}
/**
* @see java.util.Iterator#next()
*/
public final E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
ObjectIdentitySetEntry n = next;
next = next.next;
return n.object;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy