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

com.sleepycat.je.utilint.TinyHashSet Maven / Gradle / Ivy

The newest version!
/*-
 * Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle Berkeley
 * DB Java Edition made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle Berkeley DB Java Edition for a copy of the
 * license and additional information.
 */

package com.sleepycat.je.utilint;

import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

import static com.sleepycat.je.EnvironmentFailureException.assertState;

/**
 * TinyHashSet is used to optimize (for speed, not space) the case where a
 * HashSet generally holds one or two elements.  This saves us the cost of
 * creating the HashSet and related elements as well as call Object.hashCode().
 * It was designed for holding the cursors of a BIN, which are often no more
 * than two in number.
 *
 * If (elem1 != null || elem2 != null), they are the only elements in the
 * TinyHashSet.  If (set != null) then only the set's elements are in the
 * TinyHashSet.
 *
 * It should never be true that:
 *   (elem1 != null || elem2 != null) and (set != null).
 *
 * This class does not support adding null elements, and only supports a few
 * of the methods in the Set interface.
 */
public class TinyHashSet implements Iterable {

    private Set set;
    private T elem1;
    private T elem2;

    /**
     * Creates an empty set.
     */
    public TinyHashSet() {
    }

    /**
     * Creates a set with one element.
     */
    public TinyHashSet(T o) {
        elem1 = o;
    }

    /*
     * Will return a fuzzy value if not under synchronized control.
     */
    public int size() {
        if (elem1 != null && elem2 != null) {
            return 2;
        }
        if (elem1 != null || elem2 != null) {
            return 1;
        }
        if (set != null) {
            return set.size();
        }
        return 0;
    }

    public boolean contains(T o) {
        assertState(o != null);
        assertState((elem1 == null && elem2 == null) || (set == null));
        if (set != null) {
            return set.contains(o);
        }
        if (elem1 != null && (elem1 == o || elem1.equals(o))) {
            return true;
        }
        if (elem2 != null && (elem2 == o || elem2.equals(o))) {
            return true;
        }
        return false;
    }

    public boolean remove(T o) {
        assertState(o != null);
        assertState((elem1 == null && elem2 == null) || (set == null));
        if (set != null) {
            if (!set.remove(o)) {
                return false;
            }
            /*
            if (set.size() > 2) {
                return true;
            }
            final Iterator iter = set.iterator();
            if (iter.hasNext()) {
                elem1 = iter.next();
                if (iter.hasNext()) {
                    elem2 = iter.next();
                }
            }
            set = null;
            */
            return true;
        }
        if (elem1 != null && (elem1 == o || elem1.equals(o))) {
            elem1 = null;
            return true;
        }
        if (elem2 != null && (elem2 == o || elem2.equals(o))) {
            elem2 = null;
            return true;
        }
        return false;
    }

    public boolean add(T o) {
        assertState(o != null);
        assertState((elem1 == null && elem2 == null) || (set == null));
        if (set != null) {
            return set.add(o);
        }
        if (elem1 != null && (elem1 == o || elem1.equals(o))) {
            return false;
        }
        if (elem2 != null && (elem2 == o || elem2.equals(o))) {
            return false;
        }
        if (elem1 == null) {
            elem1 = o;
            return true;
        }
        if (elem2 == null) {
            elem2 = o;
            return true;
        }
        set = new HashSet(5);
        set.add(elem1);
        set.add(elem2);
        elem1 = null;
        elem2 = null;
        return set.add(o);
    }

    public Set copy() {
        assertState((elem1 == null && elem2 == null) || (set == null));
        if (set != null) {
            return new HashSet(set);
        }
        final Set ret = new HashSet();
        if (elem1 != null) {
            ret.add(elem1);
        }
        if (elem2 != null) {
            ret.add(elem2);
        }
        return ret;
    }

    public Iterator iterator() {
        assertState((elem1 == null && elem2 == null) || (set == null));
        if (set != null) {
            return set.iterator();
        }
        return new TwoElementIterator(this, elem1, elem2);
    }

    /*
     * Iterator that returns only elem1 and elem2.
     */
    private static class TwoElementIterator implements Iterator {
        final TinyHashSet parent;
        final T elem1;
        final T elem2;
        boolean returnedElem1;
        boolean returnedElem2;

        TwoElementIterator(TinyHashSet parent, T elem1, T elem2) {
            this.parent = parent;
            this.elem1 = elem1;
            this.elem2 = elem2;
            returnedElem1 = (elem1 == null);
            returnedElem2 = (elem2 == null);
        }

        public boolean hasNext() {
            return !returnedElem1 || !returnedElem2;
        }

        public T next() {
            if (!returnedElem1) {
                returnedElem1 = true;
                return elem1;
            }
            if (!returnedElem2) {
                returnedElem2 = true;
                return elem2;
            }
            throw new NoSuchElementException();
        }

        /**
         * Examine elements in the reverse order they were returned, to remove
         * the last returned element when both elements were returned.
         */
        public void remove() {
            if (returnedElem2 && elem2 != null) {
                parent.elem2 = null;
                return;
            }
            if (returnedElem1 && elem1 != null) {
                parent.elem1 = null;
                return;
            }
            assertState(false);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy