OpenIntToDoubleHashMap.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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
- *
- * https://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.
- */
- /*
- * This is not the original file distributed by the Apache Software Foundation
- * It has been modified by the Hipparchus project
- */
- package org.hipparchus.util;
- import java.io.IOException;
- import java.io.ObjectInputStream;
- import java.io.Serializable;
- import java.util.Arrays;
- import java.util.ConcurrentModificationException;
- import java.util.NoSuchElementException;
- /**
- * Open addressed map from int to double.
- * <p>This class provides a dedicated map from integers to doubles with a
- * much smaller memory overhead than standard <code>java.util.Map</code>.</p>
- * <p>This class is not synchronized. The specialized iterators returned by
- * {@link #iterator()} are fail-fast: they throw a
- * <code>ConcurrentModificationException</code> when they detect the map has been
- * modified during iteration.</p>
- */
- public class OpenIntToDoubleHashMap extends AbstractOpenIntHashMap implements Serializable {
- /** Serializable version identifier */
- private static final long serialVersionUID = 20240326L;
- /** Values table. */
- private double[] values;
- /** Return value for missing entries. */
- private final double missingEntries;
- /**
- * Build an empty map with default size and using NaN for missing entries.
- */
- public OpenIntToDoubleHashMap() {
- this(DEFAULT_EXPECTED_SIZE, Double.NaN);
- }
- /**
- * Build an empty map with default size
- * @param missingEntries value to return when a missing entry is fetched
- */
- public OpenIntToDoubleHashMap(final double missingEntries) {
- this(DEFAULT_EXPECTED_SIZE, missingEntries);
- }
- /**
- * Build an empty map with specified size and using NaN for missing entries.
- * @param expectedSize expected number of elements in the map
- */
- public OpenIntToDoubleHashMap(final int expectedSize) {
- this(expectedSize, Double.NaN);
- }
- /**
- * Build an empty map with specified size.
- * @param expectedSize expected number of elements in the map
- * @param missingEntries value to return when a missing entry is fetched
- */
- public OpenIntToDoubleHashMap(final int expectedSize,
- final double missingEntries) {
- super(expectedSize);
- values = new double[getCapacity()];
- this.missingEntries = missingEntries;
- }
- /**
- * Copy constructor.
- * @param source map to copy
- */
- public OpenIntToDoubleHashMap(final OpenIntToDoubleHashMap source) {
- super(source);
- values = new double[getCapacity()];
- System.arraycopy(source.values, 0, values, 0, getCapacity());
- missingEntries = source.missingEntries;
- }
- /**
- * Get the stored value associated with the given key
- * @param key key associated with the data
- * @return data associated with the key
- */
- public double get(final int key) {
- final int index = locate(key);
- return index < 0 ? missingEntries : values[index];
- }
- /**
- * Get an iterator over map elements.
- * <p>The specialized iterators returned are fail-fast: they throw a
- * <code>ConcurrentModificationException</code> when they detect the map
- * has been modified during iteration.</p>
- * @return iterator over the map elements
- */
- public Iterator iterator() {
- return new Iterator();
- }
- /** {@inheritDoc} */
- @Override
- public boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- final OpenIntToDoubleHashMap that = (OpenIntToDoubleHashMap) o;
- return equalKeys(that) && equalStates(that) && Arrays.equals(values, that.values);
- }
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return keysStatesHashCode() + Arrays.hashCode(values);
- }
- /**
- * Remove the value associated with a key.
- * @param key key to which the value is associated
- * @return removed value
- */
- public double remove(final int key) {
- final int index = locate(key);
- if (index < 0) {
- return missingEntries;
- } else {
- final double previous = values[index];
- doRemove(index);
- values[index] = missingEntries;
- return previous;
- }
- }
- /**
- * Put a value associated with a key in the map.
- * @param key key to which value is associated
- * @param value value to put in the map
- * @return previous value associated with the key
- */
- public double put(final int key, final double value) {
- final InsertionHolder ih = put(key);
- final double previous = ih.isExisting() ? values[ih.getIndex()] : missingEntries;
- values[ih.getIndex()] = value;
- return previous;
- }
- /** {@inheritDoc} */
- @Override
- protected int growTable(final int oldIndex) {
- final double[] newValues = new double[RESIZE_MULTIPLIER * values.length];
- final int newIndex = doGrowTable(oldIndex, (src, dest) -> newValues[dest] = values[src]);
- values = newValues;
- return newIndex;
- }
- /** Iterator class for the map. */
- public class Iterator extends BaseIterator {
- /** Get the value of current entry.
- * @return value of current entry
- * @exception ConcurrentModificationException if the map is modified during iteration
- * @exception NoSuchElementException if there is no element left in the map
- */
- public double value() throws ConcurrentModificationException, NoSuchElementException {
- return values[getCurrent()];
- }
- }
- /**
- * Read a serialized object.
- * @param stream input stream
- * @throws IOException if object cannot be read
- * @throws ClassNotFoundException if the class corresponding
- * to the serialized object cannot be found
- */
- private void readObject(final ObjectInputStream stream)
- throws IOException, ClassNotFoundException {
- stream.defaultReadObject();
- resetCount();
- }
- /**
- * Replace the instance with a data transfer object for serialization.
- * @return data transfer object that will be serialized
- */
- private Object writeReplace() {
- return new DataTransferObject(missingEntries, getSize(), iterator());
- }
- /** Internal class used only for serialization. */
- private static class DataTransferObject implements Serializable {
- /** Serializable UID. */
- private static final long serialVersionUID = 20240326L;
- /** Return value for missing entries. */
- private final double missingEntries;
- /** Keys table. */
- private final int[] keys;
- /** Values table. */
- private final double[] values;
- /** Simple constructor.
- * @param missingEntries return value for missing entries
- * @param size number of objects in the map
- * @param iterator iterator on serialized map
- */
- DataTransferObject(final double missingEntries, final int size, final Iterator iterator) {
- this.missingEntries = missingEntries;
- this.keys = new int[size];
- this.values = new double[size];
- for (int i = 0; i < size; ++i) {
- iterator.advance();
- keys[i] = iterator.key();
- values[i] = iterator.value();
- }
- }
- /** Replace the deserialized data transfer object with a {@link OpenIntToDoubleHashMap}.
- * @return replacement {@link OpenIntToDoubleHashMap}
- */
- private Object readResolve() {
- final OpenIntToDoubleHashMap map = new OpenIntToDoubleHashMap(missingEntries);
- for (int i = 0; i < keys.length; ++i) {
- map.put(keys[i], values[i]);
- }
- return map;
- }
- }
- }