OpenIntToFieldHashMap.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.util;

  22. import java.io.IOException;
  23. import java.io.ObjectInputStream;
  24. import java.io.Serializable;
  25. import java.lang.reflect.Array;
  26. import java.util.Arrays;
  27. import java.util.ConcurrentModificationException;
  28. import java.util.NoSuchElementException;

  29. import org.hipparchus.Field;
  30. import org.hipparchus.FieldElement;

  31. /**
  32.  * Open addressed map from int to FieldElement.
  33.  * <p>This class provides a dedicated map from integers to FieldElements with a
  34.  * much smaller memory overhead than standard <code>java.util.Map</code>.</p>
  35.  * <p>This class is not synchronized. The specialized iterators returned by
  36.  * {@link #iterator()} are fail-fast: they throw a
  37.  * <code>ConcurrentModificationException</code> when they detect the map has been
  38.  * modified during iteration.</p>
  39.  * @param <T> the type of the field elements
  40.  */
  41. public class OpenIntToFieldHashMap<T extends FieldElement<T>> extends AbstractOpenIntHashMap implements Serializable {

  42.     /** Serializable version identifier. */
  43.     private static final long serialVersionUID = 20240326L;

  44.     /** Field to which the elements belong. */
  45.     private final Field<T> field;

  46.     /** Values table. */
  47.     private T[] values;

  48.     /** Return value for missing entries. */
  49.     private final T missingEntries;

  50.     /**
  51.      * Build an empty map with default size and using zero for missing entries.
  52.      * @param field field to which the elements belong
  53.      */
  54.     public OpenIntToFieldHashMap(final Field<T>field) {
  55.         this(field, DEFAULT_EXPECTED_SIZE, field.getZero());
  56.     }

  57.     /**
  58.      * Build an empty map with default size
  59.      * @param field field to which the elements belong
  60.      * @param missingEntries value to return when a missing entry is fetched
  61.      */
  62.     public OpenIntToFieldHashMap(final Field<T>field, final T missingEntries) {
  63.         this(field, DEFAULT_EXPECTED_SIZE, missingEntries);
  64.     }

  65.     /**
  66.      * Build an empty map with specified size and using zero for missing entries.
  67.      * @param field field to which the elements belong
  68.      * @param expectedSize expected number of elements in the map
  69.      */
  70.     public OpenIntToFieldHashMap(final Field<T> field,final int expectedSize) {
  71.         this(field, expectedSize, field.getZero());
  72.     }

  73.     /**
  74.      * Build an empty map with specified size.
  75.      * @param field field to which the elements belong
  76.      * @param expectedSize expected number of elements in the map
  77.      * @param missingEntries value to return when a missing entry is fetched
  78.      */
  79.     public OpenIntToFieldHashMap(final Field<T> field, final int expectedSize,
  80.                                   final T missingEntries) {
  81.         super(expectedSize);
  82.         this.field          = field;
  83.         this.values         = buildArray(getCapacity());
  84.         this.missingEntries = missingEntries;
  85.     }

  86.     /**
  87.      * Copy constructor.
  88.      * @param source map to copy
  89.      */
  90.     public OpenIntToFieldHashMap(final OpenIntToFieldHashMap<T> source) {
  91.         super(source);
  92.         field = source.field;
  93.         values = buildArray(getCapacity());
  94.         System.arraycopy(source.values, 0, values, 0, getCapacity());
  95.         missingEntries = source.missingEntries;
  96.     }

  97.     /**
  98.      * Get the stored value associated with the given key
  99.      * @param key key associated with the data
  100.      * @return data associated with the key
  101.      */
  102.     public T get(final int key) {
  103.         final int index = locate(key);
  104.         return index < 0 ? missingEntries : values[index];
  105.     }

  106.     /**
  107.      * Get an iterator over map elements.
  108.      * <p>The specialized iterators returned are fail-fast: they throw a
  109.      * <code>ConcurrentModificationException</code> when they detect the map
  110.      * has been modified during iteration.</p>
  111.      * @return iterator over the map elements
  112.      */
  113.     public Iterator iterator() {
  114.         return new Iterator();
  115.     }

  116.     /** {@inheritDoc} */
  117.     @Override
  118.     public boolean equals(final Object o) {
  119.         if (this == o) {
  120.             return true;
  121.         }
  122.         if (o == null || getClass() != o.getClass()) {
  123.             return false;
  124.         }
  125.         @SuppressWarnings("unchecked")
  126.         final OpenIntToFieldHashMap<T> that = (OpenIntToFieldHashMap<T>) o;
  127.         return equalKeys(that) &&
  128.                equalStates(that) &&
  129.                field.equals(that.field) &&
  130.                Arrays.equals(values, that.values);
  131.     }

  132.     /** {@inheritDoc} */
  133.     @Override
  134.     public int hashCode() {
  135.         return keysStatesHashCode() + 67 * field.hashCode() + Arrays.hashCode(values);
  136.     }

  137.     /**
  138.      * Remove the value associated with a key.
  139.      * @param key key to which the value is associated
  140.      * @return removed value
  141.      */
  142.     public T remove(final int key) {
  143.         final int index = locate(key);
  144.         if (index < 0) {
  145.             return missingEntries;
  146.         } else {
  147.             final T previous = values[index];
  148.             doRemove(index);
  149.             values[index] = missingEntries;
  150.             return previous;
  151.         }
  152.     }

  153.     /**
  154.      * Put a value associated with a key in the map.
  155.      * @param key key to which value is associated
  156.      * @param value value to put in the map
  157.      * @return previous value associated with the key
  158.      */
  159.     public T put(final int key, final T value) {
  160.         final InsertionHolder ih = put(key);
  161.         final T previous = ih.isExisting() ? values[ih.getIndex()] : missingEntries;
  162.         values[ih.getIndex()] = value;
  163.         return previous;
  164.     }

  165.     /**
  166.      * Grow the tables.
  167.      */
  168.     @Override
  169.     protected int growTable(final int oldIndex) {
  170.         final T[] newValues = buildArray(RESIZE_MULTIPLIER * values.length);
  171.         final int newIndex  = doGrowTable(oldIndex, (src, dest) -> newValues[dest] = values[src]);
  172.         values = newValues;
  173.         return newIndex;
  174.     }

  175.     /** Iterator class for the map. */
  176.     public class Iterator extends BaseIterator {

  177.         /** Get the value of current entry.
  178.          * @return value of current entry
  179.          * @exception ConcurrentModificationException if the map is modified during iteration
  180.          * @exception NoSuchElementException if there is no element left in the map
  181.          */
  182.         public T value() throws ConcurrentModificationException, NoSuchElementException {
  183.             return values[getCurrent()];
  184.         }

  185.     }

  186.     /**
  187.      * Read a serialized object.
  188.      * @param stream input stream
  189.      * @throws IOException if object cannot be read
  190.      * @throws ClassNotFoundException if the class corresponding
  191.      * to the serialized object cannot be found
  192.      */
  193.     private void readObject(final ObjectInputStream stream)
  194.         throws IOException, ClassNotFoundException {
  195.         stream.defaultReadObject();
  196.         resetCount();
  197.     }

  198.     /** Build an array of elements.
  199.      * @param length size of the array to build
  200.      * @return a new array
  201.      */
  202.     @SuppressWarnings("unchecked") // field is of type T
  203.     private T[] buildArray(final int length) {
  204.         return (T[]) Array.newInstance(field.getRuntimeClass(), length);
  205.     }

  206. }