diff options
Diffstat (limited to 'src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java')
-rw-r--r-- | src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java | 915 |
1 files changed, 915 insertions, 0 deletions
diff --git a/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java b/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java new file mode 100644 index 0000000..b1d1912 --- /dev/null +++ b/src/main/java/org/apache/commons/math/linear/OpenMapRealVector.java @@ -0,0 +1,915 @@ +/* + * 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 + * + * 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 org.apache.commons.math.linear; + +import java.io.Serializable; + +import org.apache.commons.math.MathRuntimeException; +import org.apache.commons.math.exception.util.LocalizedFormats; +import org.apache.commons.math.util.OpenIntToDoubleHashMap; +import org.apache.commons.math.util.OpenIntToDoubleHashMap.Iterator; +import org.apache.commons.math.util.FastMath; + +/** + * This class implements the {@link RealVector} interface with a {@link OpenIntToDoubleHashMap} backing store. + * @version $Revision: 1073262 $ $Date: 2011-02-22 10:02:25 +0100 (mar. 22 févr. 2011) $ + * @since 2.0 +*/ +public class OpenMapRealVector extends AbstractRealVector implements SparseRealVector, Serializable { + + /** Default Tolerance for having a value considered zero. */ + public static final double DEFAULT_ZERO_TOLERANCE = 1.0e-12; + + /** Serializable version identifier. */ + private static final long serialVersionUID = 8772222695580707260L; + + /** Entries of the vector. */ + private final OpenIntToDoubleHashMap entries; + + /** Dimension of the vector. */ + private final int virtualSize; + + /** Tolerance for having a value considered zero. */ + private final double epsilon; + + /** + * Build a 0-length vector. + * <p>Zero-length vectors may be used to initialized construction of vectors + * by data gathering. We start with zero-length and use either the {@link + * #OpenMapRealVector(OpenMapRealVector, int)} constructor + * or one of the <code>append</code> method ({@link #append(double)}, {@link + * #append(double[])}, {@link #append(RealVector)}) to gather data + * into this vector.</p> + */ + public OpenMapRealVector() { + this(0, DEFAULT_ZERO_TOLERANCE); + } + + /** + * Construct a (dimension)-length vector of zeros. + * @param dimension size of the vector + */ + public OpenMapRealVector(int dimension) { + this(dimension, DEFAULT_ZERO_TOLERANCE); + } + + /** + * Construct a (dimension)-length vector of zeros, specifying zero tolerance. + * @param dimension Size of the vector + * @param epsilon The tolerance for having a value considered zero + */ + public OpenMapRealVector(int dimension, double epsilon) { + virtualSize = dimension; + entries = new OpenIntToDoubleHashMap(0.0); + this.epsilon = epsilon; + } + + /** + * Build a resized vector, for use with append. + * @param v The original vector + * @param resize The amount to resize it + */ + protected OpenMapRealVector(OpenMapRealVector v, int resize) { + virtualSize = v.getDimension() + resize; + entries = new OpenIntToDoubleHashMap(v.entries); + epsilon = v.epsilon; + } + + /** + * Build a vector with known the sparseness (for advanced use only). + * @param dimension The size of the vector + * @param expectedSize The expected number of non-zero entries + */ + public OpenMapRealVector(int dimension, int expectedSize) { + this(dimension, expectedSize, DEFAULT_ZERO_TOLERANCE); + } + + /** + * Build a vector with known the sparseness and zero tolerance setting (for advanced use only). + * @param dimension The size of the vector + * @param expectedSize The expected number of non-zero entries + * @param epsilon The tolerance for having a value considered zero + */ + public OpenMapRealVector(int dimension, int expectedSize, double epsilon) { + virtualSize = dimension; + entries = new OpenIntToDoubleHashMap(expectedSize, 0.0); + this.epsilon = epsilon; + } + + /** + * Create from a double array. + * Only non-zero entries will be stored + * @param values The set of values to create from + */ + public OpenMapRealVector(double[] values) { + this(values, DEFAULT_ZERO_TOLERANCE); + } + + /** + * Create from a double array, specifying zero tolerance. + * Only non-zero entries will be stored + * @param values The set of values to create from + * @param epsilon The tolerance for having a value considered zero + */ + public OpenMapRealVector(double[] values, double epsilon) { + virtualSize = values.length; + entries = new OpenIntToDoubleHashMap(0.0); + this.epsilon = epsilon; + for (int key = 0; key < values.length; key++) { + double value = values[key]; + if (!isDefaultValue(value)) { + entries.put(key, value); + } + } + } + + /** + * Create from a Double array. + * Only non-zero entries will be stored + * @param values The set of values to create from + */ + public OpenMapRealVector(Double[] values) { + this(values, DEFAULT_ZERO_TOLERANCE); + } + + /** + * Create from a Double array. + * Only non-zero entries will be stored + * @param values The set of values to create from + * @param epsilon The tolerance for having a value considered zero + */ + public OpenMapRealVector(Double[] values, double epsilon) { + virtualSize = values.length; + entries = new OpenIntToDoubleHashMap(0.0); + this.epsilon = epsilon; + for (int key = 0; key < values.length; key++) { + double value = values[key].doubleValue(); + if (!isDefaultValue(value)) { + entries.put(key, value); + } + } + } + + /** + * Copy constructor. + * @param v The instance to copy from + */ + public OpenMapRealVector(OpenMapRealVector v) { + virtualSize = v.getDimension(); + entries = new OpenIntToDoubleHashMap(v.getEntries()); + epsilon = v.epsilon; + } + + /** + * Generic copy constructor. + * @param v The instance to copy from + */ + public OpenMapRealVector(RealVector v) { + virtualSize = v.getDimension(); + entries = new OpenIntToDoubleHashMap(0.0); + epsilon = DEFAULT_ZERO_TOLERANCE; + for (int key = 0; key < virtualSize; key++) { + double value = v.getEntry(key); + if (!isDefaultValue(value)) { + entries.put(key, value); + } + } + } + + /** + * Get the entries of this instance. + * @return entries of this instance + */ + private OpenIntToDoubleHashMap getEntries() { + return entries; + } + + /** + * Determine if this value is within epsilon of zero. + * @param value The value to test + * @return <code>true</code> if this value is within epsilon to zero, <code>false</code> otherwise + * @since 2.1 + */ + protected boolean isDefaultValue(double value) { + return FastMath.abs(value) < epsilon; + } + + /** {@inheritDoc} */ + @Override + public RealVector add(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + if (v instanceof OpenMapRealVector) { + return add((OpenMapRealVector) v); + } else { + return super.add(v); + } + } + + /** + * Optimized method to add two OpenMapRealVectors. Copies the larger vector, iterates over the smaller. + * @param v Vector to add with + * @return The sum of <code>this</code> with <code>v</code> + * @throws IllegalArgumentException If the dimensions don't match + */ + public OpenMapRealVector add(OpenMapRealVector v) throws IllegalArgumentException{ + checkVectorDimensions(v.getDimension()); + boolean copyThis = entries.size() > v.entries.size(); + OpenMapRealVector res = copyThis ? this.copy() : v.copy(); + Iterator iter = copyThis ? v.entries.iterator() : entries.iterator(); + OpenIntToDoubleHashMap randomAccess = copyThis ? entries : v.entries; + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + if (randomAccess.containsKey(key)) { + res.setEntry(key, randomAccess.get(key) + iter.value()); + } else { + res.setEntry(key, iter.value()); + } + } + return res; + } + + /** + * Optimized method to append a OpenMapRealVector. + * @param v vector to append + * @return The result of appending <code>v</code> to self + */ + public OpenMapRealVector append(OpenMapRealVector v) { + OpenMapRealVector res = new OpenMapRealVector(this, v.getDimension()); + Iterator iter = v.entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + res.setEntry(iter.key() + virtualSize, iter.value()); + } + return res; + } + + /** {@inheritDoc} */ + public OpenMapRealVector append(RealVector v) { + if (v instanceof OpenMapRealVector) { + return append((OpenMapRealVector) v); + } + return append(v.getData()); + } + + /** {@inheritDoc} */ + public OpenMapRealVector append(double d) { + OpenMapRealVector res = new OpenMapRealVector(this, 1); + res.setEntry(virtualSize, d); + return res; + } + + /** {@inheritDoc} */ + public OpenMapRealVector append(double[] a) { + OpenMapRealVector res = new OpenMapRealVector(this, a.length); + for (int i = 0; i < a.length; i++) { + res.setEntry(i + virtualSize, a[i]); + } + return res; + } + + /** + * {@inheritDoc} + * @since 2.1 + */ + @Override + public OpenMapRealVector copy() { + return new OpenMapRealVector(this); + } + + /** + * Optimized method to compute the dot product with an OpenMapRealVector. + * Iterates over the smaller of the two. + * @param v The vector to compute the dot product with + * @return The dot product of <code>this</code> and <code>v</code> + * @throws IllegalArgumentException If the dimensions don't match + */ + public double dotProduct(OpenMapRealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + boolean thisIsSmaller = entries.size() < v.entries.size(); + Iterator iter = thisIsSmaller ? entries.iterator() : v.entries.iterator(); + OpenIntToDoubleHashMap larger = thisIsSmaller ? v.entries : entries; + double d = 0; + while(iter.hasNext()) { + iter.advance(); + d += iter.value() * larger.get(iter.key()); + } + return d; + } + + /** {@inheritDoc} */ + @Override + public double dotProduct(RealVector v) throws IllegalArgumentException { + if(v instanceof OpenMapRealVector) { + return dotProduct((OpenMapRealVector)v); + } else { + return super.dotProduct(v); + } + } + + /** {@inheritDoc} */ + public OpenMapRealVector ebeDivide(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + OpenMapRealVector res = new OpenMapRealVector(this); + Iterator iter = res.entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + res.setEntry(iter.key(), iter.value() / v.getEntry(iter.key())); + } + return res; + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector ebeDivide(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + OpenMapRealVector res = new OpenMapRealVector(this); + Iterator iter = res.entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + res.setEntry(iter.key(), iter.value() / v[iter.key()]); + } + return res; + } + + /** {@inheritDoc} */ + public OpenMapRealVector ebeMultiply(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + OpenMapRealVector res = new OpenMapRealVector(this); + Iterator iter = res.entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + res.setEntry(iter.key(), iter.value() * v.getEntry(iter.key())); + } + return res; + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector ebeMultiply(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + OpenMapRealVector res = new OpenMapRealVector(this); + Iterator iter = res.entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + res.setEntry(iter.key(), iter.value() * v[iter.key()]); + } + return res; + } + + /** {@inheritDoc} */ + public OpenMapRealVector getSubVector(int index, int n) throws MatrixIndexException { + checkIndex(index); + checkIndex(index + n - 1); + OpenMapRealVector res = new OpenMapRealVector(n); + int end = index + n; + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + if (key >= index && key < end) { + res.setEntry(key - index, iter.value()); + } + } + return res; + } + + /** {@inheritDoc} */ + @Override + public double[] getData() { + double[] res = new double[virtualSize]; + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + res[iter.key()] = iter.value(); + } + return res; + } + + /** {@inheritDoc} */ + public int getDimension() { + return virtualSize; + } + + /** + * Optimized method to compute distance. + * @param v The vector to compute distance to + * @return The distance from <code>this</code> and <code>v</code> + * @throws IllegalArgumentException If the dimensions don't match + */ + public double getDistance(OpenMapRealVector v) throws IllegalArgumentException { + Iterator iter = entries.iterator(); + double res = 0; + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + double delta; + delta = iter.value() - v.getEntry(key); + res += delta * delta; + } + iter = v.getEntries().iterator(); + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + if (!entries.containsKey(key)) { + final double value = iter.value(); + res += value * value; + } + } + return FastMath.sqrt(res); + } + + /** {@inheritDoc} */ + @Override + public double getDistance(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + if (v instanceof OpenMapRealVector) { + return getDistance((OpenMapRealVector) v); + } + return getDistance(v.getData()); + } + + /** {@inheritDoc} */ + @Override + public double getDistance(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + double res = 0; + for (int i = 0; i < v.length; i++) { + double delta = entries.get(i) - v[i]; + res += delta * delta; + } + return FastMath.sqrt(res); + } + + /** {@inheritDoc} */ + public double getEntry(int index) throws MatrixIndexException { + checkIndex(index); + return entries.get(index); + } + + /** + * Distance between two vectors. + * <p>This method computes the distance consistent with + * L<sub>1</sub> norm, i.e. the sum of the absolute values of + * elements differences.</p> + * @param v vector to which distance is requested + * @return distance between two vectors. + */ + public double getL1Distance(OpenMapRealVector v) { + double max = 0; + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + double delta = FastMath.abs(iter.value() - v.getEntry(iter.key())); + max += delta; + } + iter = v.getEntries().iterator(); + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + if (!entries.containsKey(key)) { + double delta = FastMath.abs(iter.value()); + max += FastMath.abs(delta); + } + } + return max; + } + + /** {@inheritDoc} */ + @Override + public double getL1Distance(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + if (v instanceof OpenMapRealVector) { + return getL1Distance((OpenMapRealVector) v); + } + return getL1Distance(v.getData()); + } + + /** {@inheritDoc} */ + @Override + public double getL1Distance(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + double max = 0; + for (int i = 0; i < v.length; i++) { + double delta = FastMath.abs(getEntry(i) - v[i]); + max += delta; + } + return max; + } + + /** + * Optimized method to compute LInfDistance. + * @param v The vector to compute from + * @return the LInfDistance + */ + private double getLInfDistance(OpenMapRealVector v) { + double max = 0; + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + double delta = FastMath.abs(iter.value() - v.getEntry(iter.key())); + if (delta > max) { + max = delta; + } + } + iter = v.getEntries().iterator(); + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + if (!entries.containsKey(key)) { + if (iter.value() > max) { + max = iter.value(); + } + } + } + return max; + } + + /** {@inheritDoc} */ + @Override + public double getLInfDistance(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + if (v instanceof OpenMapRealVector) { + return getLInfDistance((OpenMapRealVector) v); + } + return getLInfDistance(v.getData()); + } + + /** {@inheritDoc} */ + @Override + public double getLInfDistance(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + double max = 0; + for (int i = 0; i < v.length; i++) { + double delta = FastMath.abs(getEntry(i) - v[i]); + if (delta > max) { + max = delta; + } + } + return max; + } + + /** {@inheritDoc} */ + public boolean isInfinite() { + boolean infiniteFound = false; + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + final double value = iter.value(); + if (Double.isNaN(value)) { + return false; + } + if (Double.isInfinite(value)) { + infiniteFound = true; + } + } + return infiniteFound; + } + + /** {@inheritDoc} */ + public boolean isNaN() { + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + if (Double.isNaN(iter.value())) { + return true; + } + } + return false; + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector mapAdd(double d) { + return copy().mapAddToSelf(d); + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector mapAddToSelf(double d) { + for (int i = 0; i < virtualSize; i++) { + setEntry(i, getEntry(i) + d); + } + return this; + } + + /** {@inheritDoc} */ + @Override + public RealMatrix outerProduct(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + RealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize); + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + int row = iter.key(); + double value = iter.value(); + for (int col = 0; col < virtualSize; col++) { + res.setEntry(row, col, value * v[col]); + } + } + return res; + } + + /** {@inheritDoc} */ + public RealVector projection(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + return v.mapMultiply(dotProduct(v) / v.dotProduct(v)); + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector projection(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + return (OpenMapRealVector) projection(new OpenMapRealVector(v)); + } + + /** {@inheritDoc} */ + public void setEntry(int index, double value) throws MatrixIndexException { + checkIndex(index); + if (!isDefaultValue(value)) { + entries.put(index, value); + } else if (entries.containsKey(index)) { + entries.remove(index); + } + } + + /** {@inheritDoc} */ + @Override + public void setSubVector(int index, RealVector v) throws MatrixIndexException { + checkIndex(index); + checkIndex(index + v.getDimension() - 1); + setSubVector(index, v.getData()); + } + + /** {@inheritDoc} */ + @Override + public void setSubVector(int index, double[] v) throws MatrixIndexException { + checkIndex(index); + checkIndex(index + v.length - 1); + for (int i = 0; i < v.length; i++) { + setEntry(i + index, v[i]); + } + } + + /** {@inheritDoc} */ + @Override + public void set(double value) { + for (int i = 0; i < virtualSize; i++) { + setEntry(i, value); + } + } + + /** + * Optimized method to subtract OpenMapRealVectors. + * @param v The vector to subtract from <code>this</code> + * @return The difference of <code>this</code> and <code>v</code> + * @throws IllegalArgumentException If the dimensions don't match + */ + public OpenMapRealVector subtract(OpenMapRealVector v) throws IllegalArgumentException{ + checkVectorDimensions(v.getDimension()); + OpenMapRealVector res = copy(); + Iterator iter = v.getEntries().iterator(); + while (iter.hasNext()) { + iter.advance(); + int key = iter.key(); + if (entries.containsKey(key)) { + res.setEntry(key, entries.get(key) - iter.value()); + } else { + res.setEntry(key, -iter.value()); + } + } + return res; + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector subtract(RealVector v) throws IllegalArgumentException { + checkVectorDimensions(v.getDimension()); + if (v instanceof OpenMapRealVector) { + return subtract((OpenMapRealVector) v); + } + return subtract(v.getData()); + } + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector subtract(double[] v) throws IllegalArgumentException { + checkVectorDimensions(v.length); + OpenMapRealVector res = new OpenMapRealVector(this); + for (int i = 0; i < v.length; i++) { + if (entries.containsKey(i)) { + res.setEntry(i, entries.get(i) - v[i]); + } else { + res.setEntry(i, -v[i]); + } + } + return res; + } + + + /** {@inheritDoc} */ + @Override + public OpenMapRealVector unitVector() { + OpenMapRealVector res = copy(); + res.unitize(); + return res; + } + + /** {@inheritDoc} */ + @Override + public void unitize() { + double norm = getNorm(); + if (isDefaultValue(norm)) { + throw MathRuntimeException.createArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); + } + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + entries.put(iter.key(), iter.value() / norm); + } + + } + + + /** {@inheritDoc} */ + @Override + public double[] toArray() { + return getData(); + } + + /** {@inheritDoc} + * <p> Implementation Note: This works on exact values, and as a result + * it is possible for {@code a.subtract(b)} to be the zero vector, while + * {@code a.hashCode() != b.hashCode()}.</p> + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(epsilon); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + virtualSize; + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + temp = Double.doubleToLongBits(iter.value()); + result = prime * result + (int) (temp ^ (temp >>32)); + } + return result; + } + + /** + * <p> Implementation Note: This performs an exact comparison, and as a result + * it is possible for {@code a.subtract(b}} to be the zero vector, while + * {@code a.equals(b) == false}.</p> + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof OpenMapRealVector)) { + return false; + } + OpenMapRealVector other = (OpenMapRealVector) obj; + if (virtualSize != other.virtualSize) { + return false; + } + if (Double.doubleToLongBits(epsilon) != + Double.doubleToLongBits(other.epsilon)) { + return false; + } + Iterator iter = entries.iterator(); + while (iter.hasNext()) { + iter.advance(); + double test = other.getEntry(iter.key()); + if (Double.doubleToLongBits(test) != Double.doubleToLongBits(iter.value())) { + return false; + } + } + iter = other.getEntries().iterator(); + while (iter.hasNext()) { + iter.advance(); + double test = iter.value(); + if (Double.doubleToLongBits(test) != Double.doubleToLongBits(getEntry(iter.key()))) { + return false; + } + } + return true; + } + + /** + * + * @return the percentage of none zero elements as a decimal percent. + * @deprecated as of 2.2 replaced by the correctly spelled {@link #getSparsity()} + */ + @Deprecated + public double getSparcity() { + return getSparsity(); + } + + /** + * + * @return the percentage of none zero elements as a decimal percent. + * @since 2.2 + */ + public double getSparsity() { + return (double)entries.size()/(double)getDimension(); + } + + /** {@inheritDoc} */ + @Override + public java.util.Iterator<Entry> sparseIterator() { + return new OpenMapSparseIterator(); + } + + /** + * Implementation of <code>Entry</code> optimized for OpenMap. + * <p>This implementation does not allow arbitrary calls to <code>setIndex</code> + * since the order that entries are returned is undefined. + */ + protected class OpenMapEntry extends Entry { + + /** Iterator pointing to the entry. */ + private final Iterator iter; + + /** Build an entry from an iterator point to an element. + * @param iter iterator pointing to the entry + */ + protected OpenMapEntry(Iterator iter) { + this.iter = iter; + } + + /** {@inheritDoc} */ + @Override + public double getValue() { + return iter.value(); + } + + /** {@inheritDoc} */ + @Override + public void setValue(double value) { + entries.put(iter.key(), value); + } + + /** {@inheritDoc} */ + @Override + public int getIndex() { + return iter.key(); + } + + } + + /** + * Iterator class to do iteration over just the non-zero elements. + * <p>This implementation is fail-fast, so cannot be used to modify any zero element. + * + */ + protected class OpenMapSparseIterator implements java.util.Iterator<Entry> { + + /** Underlying iterator. */ + private final Iterator iter; + + /** Current entry. */ + private final Entry current; + + /** Simple constructor. */ + protected OpenMapSparseIterator() { + iter = entries.iterator(); + current = new OpenMapEntry(iter); + } + + /** {@inheritDoc} */ + public boolean hasNext() { + return iter.hasNext(); + } + + /** {@inheritDoc} */ + public Entry next() { + iter.advance(); + return current; + } + + /** {@inheritDoc} */ + public void remove() { + throw new UnsupportedOperationException("Not supported"); + } + + } +} |