/*
* #!
* Ontopia Engine
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* 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.
* !#
*/
package net.ontopia.utils;
// WARNING: This class is a direct copy of the CompactHashSet.java
// class, but with two changes. The while(...) calls has been changes
// to the new semantics and the use of hashCode() minimized. These
// changes should be repeated every time the CompactHashSet.java
// changes.
import java.util.Collection;
/**
* INTERNAL: This class is a specialization of the CompactHashSet
* class, and uses the == operator to compare objects.
*/
public class CompactIdentityHashSet<E> extends CompactHashSet<E> {
public CompactIdentityHashSet() {
}
public CompactIdentityHashSet(int size) {
super(size);
}
public CompactIdentityHashSet(Collection<E> coll) {
super(coll);
}
// ===== SET IMPLEMENTATION ================================================
/**
* Returns <tt>true</tt> if this set contains the specified element.
*
* @param o element whose presence in this set is to be tested.
* @return <tt>true</tt> if this set contains the specified element.
*/
public boolean contains(Object o) {
if (o == null) o = nullObject;
int index = (System.identityHashCode(o) & 0x7FFFFFFF) % objects.length;
int offset = 1;
// search for the object (continue while !null and !this object)
while(objects[index] != null && objects[index] != o) {
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
offset = offset*2 + 1;
if (offset == -1)
offset = 2;
}
return objects[index] != null;
}
/**
* Adds the specified element to this set if it is not already
* present.
*
* @param o element to be added to this set.
* @return <tt>true</tt> if the set did not already contain the specified
* element.
*/
public boolean add(Object o) {
if (o == null) o = nullObject;
int index = (System.identityHashCode(o) & 0x7FFFFFFF) % objects.length;
int offset = 1;
int deletedix = -1;
// search for the object (continue while !null and !this object)
while(objects[index] != null && objects[index] != o) {
// if there's a deleted object here we can put this object here,
// provided it's not in here somewhere else already
if (objects[index] == deletedObject)
deletedix = index;
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
offset = offset*2 + 1;
if (offset == -1)
offset = 2;
}
if (objects[index] == null) { // wasn't present already
if (deletedix != -1) // reusing a deleted cell
index = deletedix;
else
freecells--;
modCount++;
elements++;
objects[index] = (E)o;
// rehash with same capacity
if (1 - (freecells / (double) objects.length) > LOAD_FACTOR)
rehash();
return true;
} else // was there already
return false;
}
/**
* Removes the specified element from the set.
*/
public boolean remove(Object o) {
if (o == null) o = nullObject;
int index = (System.identityHashCode(o) & 0x7FFFFFFF) % objects.length;
int offset = 1;
// search for the object (continue while !null and !this object)
while(objects[index] != null && objects[index] != o) {
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
offset = offset*2 + 1;
if (offset == -1)
offset = 2;
}
// we found the right position, now do the removal
if (objects[index] != null) {
// we found the object
objects[index] = (E)deletedObject;
modCount++;
elements--;
return true;
} else
// we did not find the object
return false;
}
// ===== INTERNAL METHODS ==================================================
/**
* INTERNAL: Rehashes the hashset to a bigger size.
*/
protected void rehash(int newCapacity) {
int oldCapacity = objects.length;
E[] newObjects = (E[]) new Object[newCapacity];
for (int ix = 0; ix < oldCapacity; ix++) {
E o = objects[ix];
if (o == null || o == deletedObject)
continue;
int index = (System.identityHashCode(o) & 0x7FFFFFFF) % newCapacity;
int offset = 1;
// search for the object
while(newObjects[index] != null) { // no need to test for duplicates
index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
offset = offset*2 + 1;
if (offset == -1)
offset = 2;
}
newObjects[index] = o;
}
objects = newObjects;
freecells = objects.length - elements;
}
}