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

org.zoodb.jdo.internal.util.ObjectIdentitySet Maven / Gradle / Ivy

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 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