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

com.epam.deltix.util.collections.generated.IntegerToObjectHashMap Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2021 EPAM Systems, Inc
 *
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership. 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 com.epam.deltix.util.collections.generated;

import com.epam.deltix.util.collections.hash.*;
import com.epam.deltix.util.collections.*;
import java.io.*;
import java.util.*;
import java.util.function.Consumer;

@SuppressWarnings ("unchecked")
public class IntegerToObjectHashMap 

    extends IntegerHashMapBase 
    implements Iterable 
{
    protected Object [] values;

    public IntegerToObjectHashMap () {
        super ();
    }

    public IntegerToObjectHashMap (int cap) {
        super (cap);
    }

    public IntegerToObjectHashMap (HashCodeComputer hashCodeComputer) {
        super (0, hashCodeComputer);
    }

    public IntegerToObjectHashMap (int cap, HashCodeComputer hashCodeComputer) {
        super (cap, hashCodeComputer);
    }

    @Override
    protected void              allocTable (int cap) {
        super.allocTable (cap);

        values = new Object [cap];
    }

    @Override
    public long                 getSizeInMemory () {
        return (
            super.getSizeInMemory () + (SIZE_OF_POINTER + ARRAY_OVERHEAD) +
            values.length * SIZE_OF_POINTER
        );
    }

    @Override
    public void             clear () {
        super.clear ();
        Arrays.fill (values, null);
    }

    @Override
    protected void          free (int idx) {
        super.free (idx);
        values [idx] = null;
    }

    class ElementIterator implements Iterator  {
        private int             pos = -1;

    	public ElementIterator () {
    		move ();
    	}

    	private void            move () {
    		do {
    			pos++;
    		} while (pos < values.length && isEmpty (pos));
    	}

        @Override
    	public boolean          hasNext () {
    		return (pos < values.length);
    	}

        @Override
    	public V                next () {
    		V   ret = (V) values [pos];
    		move ();
    		return (ret);
    	}

        @Override
        public void     remove () {
            throw new UnsupportedOperationException ();
        }
    }

    @Override
    public Iterator      iterator () {
        return (new ElementIterator ());
    }

    @Override
    public void forEach(Consumer consumer) {
        for (int i = 0; i < values.length; i++) {
            if (isFilled (i)) {
                consumer.accept((V) values[i]);
            }
        }
    }

    protected void              resizeTable (int newSize) {
        final int                   curLength = values.length;
        final int []            saveKeys = keys;
        final Object []             saveValues = values;
        final int []                savePrev = prev;

        allocTable (newSize);

        for (int ii = 0; ii < curLength; ii++)
            if (savePrev [ii] != NULL)
                putNewNoSpaceCheck (saveKeys [ii], (V)saveValues [ii]);
    }

    public V               get (int key, V notFoundValue) {
        int         pos = find (key);

        return (pos == NULL ? notFoundValue : (V)values [pos]);
    }

    /**
     *  Remove a value, if existed.
     *
     *  @param key          The key
     *  @param notFoundValue This will be returned if the key was not associated with a value.
     *  @return The old value associated with the key, or notFoundValue.
     */
    public V               remove (int key, V notFoundValue) {
        int         idx = find (key);

        if (idx == NULL)
            return (notFoundValue);

        V        value = (V)values [idx];

        free (idx);

        return (value);
    }

    private void                putNewNoSpaceCheck (int key, V value) {
        int         hidx = hashIndex (key);
        int         idx = find (hidx, key);

        if (idx != NULL)
            throw new IllegalArgumentException (
                "Value for key " + key + " already exists = " + value
            );

        idx = allocEntry (hidx);

        values [idx] = value;
        putKey(idx, key);
    }

    /**
     *  Put new element into the map
     *
     *  @param key       The key
     *  @param value     The value
     *  @return  true if the element is new, false if the key was found.
     */
    public boolean              put (int key, V value) {
        int         hidx = hashIndex (key);
        int         idx = find (hidx, key);

        if (idx != NULL) {
            values [idx] = value;
            return (false);
        }

        if (freeHead == NULL) {
            resizeTable (values.length * 2);
            hidx = hashIndex (key); // recompute!
        }

        idx = allocEntry (hidx);

        values [idx] = value;
        putKey (idx, key);

        return (true);
    }

    /**
     *  Replace a value and return the old one.
     *  @param key          The key
     *  @param value        The new value to put in table
     *  @param notFoundValue This will be returned if the key was not associated with a value.
     *  @return The old value associated with the key, or notFoundValue.
     */
    public V               putAndGet (
        int                       key,
        V                     value,
        V                     notFoundValue
    )
    {
        int         hidx = hashIndex (key);
        int         idx = find (hidx, key);

        if (idx != NULL) {
            V    old = (V)values [idx];

            values [idx] = value;

            return (old);
        }

        if (freeHead == NULL) {
            resizeTable (values.length * 2);
            hidx = hashIndex (key); // recompute!
        }

        idx = allocEntry (hidx);

        values [idx] = value;
        putKey(idx, key);

        return (notFoundValue);
    }

    /**
     *  Put new value into the map only if there is no previously stored value under the same key.
     *
     *  @param key          The key
     *  @param value        The new value to put in table (but only if the key is not occupied)
     *  @return             Value that remains in the map.
     */
    public V               putAndGetIfEmpty (
        int                   key,
        V                 value
    )
    {
        int         hidx = hashIndex (key);
        int         idx = find (hidx, key);

        if (idx != NULL) {
            return (V) values [idx];
        }

        if (freeHead == NULL) {
            resizeTable (values.length * 2);
            hidx = hashIndex (key); // recompute!
        }

        idx = allocEntry (hidx);

        values [idx] = value;
        putKey(idx, key);

        return value;
    }

    /**
     *  Put new value into the map only if there is no previously stored value under the same key.
     *
     *  @param key          The key
     *  @param value        The new value to put in table (but only if the key is not occupied)
     *  @return             True if this map has changed as the result of this call.
     */
    public boolean               putIfEmpty (
        int                   key,
        V                 value
    )
    {
        int         hidx = hashIndex (key);
        int         idx = find (hidx, key);

        if (idx != NULL) {
            return false;
        }

        if (freeHead == NULL) {
            resizeTable (values.length * 2);
            hidx = hashIndex (key); // recompute!
        }

        idx = allocEntry (hidx);

        values [idx] = value;
        putKey(idx, key);

        return true;
    }


    /**
     *	Linearly searches for the specified value.
     *
     *  @param value    The value to search.
     *  @return         Whether the specified value is found.
     */
    public final boolean        containsValue (V value) {
    	int         tabSize = values.length;

    	for (int ii = 0; ii < tabSize; ii++)
    		if (isFilled (ii) && values [ii] == value)
    			return (true);

    	return (false);
    }

    public final Object []   valuesToArray (Object [] ret) {
        if (ret == null || ret.length < count)
            ret = new Object [count];

        final int       tabSize = values.length;
        int             outIdx = 0;

        for (int ii = 0; ii < tabSize; ii++)
            if (isFilled (ii))
                ret [outIdx++] = values [ii];

        assert outIdx == count;

        return ret;
    }

    /** Method copies content of this map into the map provided as argument. NOTE: destination is not cleaned. */
    public void copyTo (Collection result) {
        final int       tabSize = values.length;
        for (int ii = 0; ii < tabSize; ii++)
            if (isFilled (ii))
                result.add((V)values [ii]);

    }

    protected final class ElementEnumeration
        implements ElementsEnumeration , IntegerEntry
    {
    	private int             pos = -1;

    	public ElementEnumeration () {
    		move ();
    	}

    	private void            move () {
    		do {
    			pos++;
    		} while (pos < values.length && isEmpty (pos));
    	}

        @Override
    	public boolean          hasMoreElements () {
    		return (pos < values.length);
    	}

        @Override
        public void             reset() {
            pos = -1;
            move();
        }

        @Override
    	public V                nextElement () {
    		V   ret = (V) values [pos];
    		move ();
    		return (ret);
    	}

        @Override
	    public Integer            key () {
           return keys [pos];
        }

        @Override
	    public int            keyInteger () {
           return (keys [pos]);
        }
    }

    public ElementsEnumeration       elements () {
    	return (new ElementEnumeration ());
    }

    @Override
    public final boolean        equals (Object o) {
        throw new UnsupportedOperationException ();
    }

    @Override
    public int                  hashCode () {
        throw new UnsupportedOperationException ();
    }

    static final long           serialVersionUID = 1L;

    private void                writeObject (ObjectOutputStream out)
        throws IOException
    {
        out.writeShort (1);
        out.writeInt (size ());

        final int       tabSize = values.length;
        int             numWritten = 0;

        for (int ii = 0; ii < tabSize; ii++) {
            if (isFilled (ii)) {
                numWritten++;
 				out.writeInt (keys [ii]);
                out.writeObject (values [ii]);
            }
        }

        if (numWritten != size ())
            throw new RuntimeException (
                "Size mismatch: " + numWritten + " instead of " + size ()
            );
    }

    private void                readObject (ObjectInputStream in)
        throws IOException, ClassNotFoundException
    {
    	@SuppressWarnings("unused")
        short           readSerialVersion = in.readShort();

        int             inCount = in.readInt ();

        allocTable (Math.max(inCount, MIN_CAPACITY)); // allocate not less than MIN_CAPACITY

        for (int ii = 0; ii < inCount; ii++) {
            int       key = in.readInt ();
            V     value = (V)in.readObject ();

            put (key, value);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy