/*
* Copyright (C) 2002-2019 Sebastiano Vigna
*
* 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 it.unimi.dsi.fastutil.doubles;
import it.unimi.dsi.fastutil.objects.ReferenceCollection;
import it.unimi.dsi.fastutil.objects.AbstractReferenceCollection;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
import java.util.Iterator;
import java.util.Map;
An abstract class providing basic methods for maps implementing a
type-specific interface.
Optional operations just throw an UnsupportedOperationException
. Generic versions of accessors delegate to the corresponding type-specific counterparts following the interface rules (they take care of returning null
on a missing key).
As a further help, this class provides a BasicEntry
inner class that implements a type-specific version of Entry
; it is particularly useful for those classes that do not implement their own entries (e.g., most immutable maps).
/**
* An abstract class providing basic methods for maps implementing a
* type-specific interface.
*
* <p>
* Optional operations just throw an {@link UnsupportedOperationException}.
* Generic versions of accessors delegate to the corresponding type-specific
* counterparts following the interface rules (they take care of returning
* {@code null} on a missing key).
*
* <p>
* As a further help, this class provides a {@link BasicEntry BasicEntry} inner
* class that implements a type-specific version of {@link java.util.Map.Entry};
* it is particularly useful for those classes that do not implement their own
* entries (e.g., most immutable maps).
*/
public abstract class AbstractDouble2ReferenceMap<V> extends AbstractDouble2ReferenceFunction<V>
implements
Double2ReferenceMap<V>,
java.io.Serializable {
private static final long serialVersionUID = -4940583368468432370L;
protected AbstractDouble2ReferenceMap() {
}
@Override
public boolean containsValue(final Object v) {
return values().contains(v);
}
@Override
public boolean containsKey(final double k) {
final ObjectIterator<Double2ReferenceMap.Entry<V>> i = double2ReferenceEntrySet().iterator();
while (i.hasNext())
if (i.next().getDoubleKey() == k)
return true;
return false;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
This class provides a basic but complete type-specific entry class for all
those maps implementations that do not have entries on their own (e.g., most
immutable maps).
This class does not implement
setValue()
, as the modification would not be reflected in the base map.
/**
* This class provides a basic but complete type-specific entry class for all
* those maps implementations that do not have entries on their own (e.g., most
* immutable maps).
*
* <p>
* This class does not implement {@link java.util.Map.Entry#setValue(Object)
* setValue()}, as the modification would not be reflected in the base map.
*/
public static class BasicEntry<V> implements Double2ReferenceMap.Entry<V> {
protected double key;
protected V value;
public BasicEntry() {
}
public BasicEntry(final Double key, final V value) {
this.key = (key).doubleValue();
this.value = (value);
}
public BasicEntry(final double key, final V value) {
this.key = key;
this.value = value;
}
@Override
public double getDoubleKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(final V value) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(final Object o) {
if (!(o instanceof Map.Entry))
return false;
if (o instanceof Double2ReferenceMap.Entry) {
final Double2ReferenceMap.Entry<V> e = (Double2ReferenceMap.Entry<V>) o;
return (Double.doubleToLongBits(key) == Double.doubleToLongBits(e.getDoubleKey()))
&& ((value) == (e.getValue()));
}
final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
final Object key = e.getKey();
if (key == null || !(key instanceof Double))
return false;
final Object value = e.getValue();
return (Double.doubleToLongBits(this.key) == Double.doubleToLongBits(((Double) (key)).doubleValue()))
&& ((this.value) == ((value)));
}
@Override
public int hashCode() {
return it.unimi.dsi.fastutil.HashCommon.double2int(key)
^ ((value) == null ? 0 : System.identityHashCode(value));
}
@Override
public String toString() {
return key + "->" + value;
}
}
This class provides a basic implementation for an Entry set which forwards
some queries to the map.
/**
* This class provides a basic implementation for an Entry set which forwards
* some queries to the map.
*/
public abstract static class BasicEntrySet<V> extends AbstractObjectSet<Entry<V>> {
protected final Double2ReferenceMap<V> map;
public BasicEntrySet(final Double2ReferenceMap<V> map) {
this.map = map;
}
@SuppressWarnings("unchecked")
@Override
public boolean contains(final Object o) {
if (!(o instanceof Map.Entry))
return false;
if (o instanceof Double2ReferenceMap.Entry) {
final Double2ReferenceMap.Entry<V> e = (Double2ReferenceMap.Entry<V>) o;
final double k = e.getDoubleKey();
return map.containsKey(k) && ((map.get(k)) == (e.getValue()));
}
final Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
final Object key = e.getKey();
if (key == null || !(key instanceof Double))
return false;
final double k = ((Double) (key)).doubleValue();
final Object value = e.getValue();
return map.containsKey(k) && ((map.get(k)) == ((value)));
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(final Object o) {
if (!(o instanceof Map.Entry))
return false;
if (o instanceof Double2ReferenceMap.Entry) {
final Double2ReferenceMap.Entry<V> e = (Double2ReferenceMap.Entry<V>) o;
return map.remove(e.getDoubleKey(), e.getValue());
}
Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
final Object key = e.getKey();
if (key == null || !(key instanceof Double))
return false;
final double k = ((Double) (key)).doubleValue();
final Object v = e.getValue();
return map.remove(k, v);
}
@Override
public int size() {
return map.size();
}
}
Returns a type-specific-set view of the keys of this map.
The view is backed by the set returned by Map.entrySet()
. Note that no attempt is made at caching the result of this method, as this
would require adding some attributes that lightweight implementations would
not need. Subclasses may easily override this policy by calling this method
and caching the result, but implementors are encouraged to write more
efficient ad-hoc implementations.
Returns: a set view of the keys of this map; it may be safely cast to a
type-specific interface.
/**
* Returns a type-specific-set view of the keys of this map.
*
* <p>
* The view is backed by the set returned by {@link Map#entrySet()}. Note that
* <em>no attempt is made at caching the result of this method</em>, as this
* would require adding some attributes that lightweight implementations would
* not need. Subclasses may easily override this policy by calling this method
* and caching the result, but implementors are encouraged to write more
* efficient ad-hoc implementations.
*
* @return a set view of the keys of this map; it may be safely cast to a
* type-specific interface.
*/
@Override
public DoubleSet keySet() {
return new AbstractDoubleSet() {
@Override
public boolean contains(final double k) {
return containsKey(k);
}
@Override
public int size() {
return AbstractDouble2ReferenceMap.this.size();
}
@Override
public void clear() {
AbstractDouble2ReferenceMap.this.clear();
}
@Override
public DoubleIterator iterator() {
return new DoubleIterator() {
private final ObjectIterator<Double2ReferenceMap.Entry<V>> i = Double2ReferenceMaps
.fastIterator(AbstractDouble2ReferenceMap.this);
@Override
public double nextDouble() {
return i.next().getDoubleKey();
};
@Override
public boolean hasNext() {
return i.hasNext();
}
@Override
public void remove() {
i.remove();
}
};
}
};
}
Returns a type-specific-set view of the values of this map.
The view is backed by the set returned by Map.entrySet()
. Note that no attempt is made at caching the result of this method, as this
would require adding some attributes that lightweight implementations would
not need. Subclasses may easily override this policy by calling this method
and caching the result, but implementors are encouraged to write more
efficient ad-hoc implementations.
Returns: a set view of the values of this map; it may be safely cast to a
type-specific interface.
/**
* Returns a type-specific-set view of the values of this map.
*
* <p>
* The view is backed by the set returned by {@link Map#entrySet()}. Note that
* <em>no attempt is made at caching the result of this method</em>, as this
* would require adding some attributes that lightweight implementations would
* not need. Subclasses may easily override this policy by calling this method
* and caching the result, but implementors are encouraged to write more
* efficient ad-hoc implementations.
*
* @return a set view of the values of this map; it may be safely cast to a
* type-specific interface.
*/
@Override
public ReferenceCollection<V> values() {
return new AbstractReferenceCollection<V>() {
@Override
public boolean contains(final Object k) {
return containsValue(k);
}
@Override
public int size() {
return AbstractDouble2ReferenceMap.this.size();
}
@Override
public void clear() {
AbstractDouble2ReferenceMap.this.clear();
}
@Override
public ObjectIterator<V> iterator() {
return new ObjectIterator<V>() {
private final ObjectIterator<Double2ReferenceMap.Entry<V>> i = Double2ReferenceMaps
.fastIterator(AbstractDouble2ReferenceMap.this);
@Override
public V next() {
return i.next().getValue();
}
@Override
public boolean hasNext() {
return i.hasNext();
}
};
}
};
}
{@inheritDoc} /** {@inheritDoc} */
@SuppressWarnings({"unchecked", "deprecation"})
@Override
public void putAll(final Map<? extends Double, ? extends V> m) {
if (m instanceof Double2ReferenceMap) {
ObjectIterator<Double2ReferenceMap.Entry<V>> i = Double2ReferenceMaps
.fastIterator((Double2ReferenceMap<V>) m);
while (i.hasNext()) {
final Double2ReferenceMap.Entry<? extends V> e = i.next();
put(e.getDoubleKey(), e.getValue());
}
} else {
int n = m.size();
final Iterator<? extends Map.Entry<? extends Double, ? extends V>> i = m.entrySet().iterator();
Map.Entry<? extends Double, ? extends V> e;
while (n-- != 0) {
e = i.next();
put(e.getKey(), e.getValue());
}
}
}
Returns a hash code for this map.
The hash code of a map is computed by summing the hash codes of its entries.
Returns: a hash code for this map.
/**
* Returns a hash code for this map.
*
* The hash code of a map is computed by summing the hash codes of its entries.
*
* @return a hash code for this map.
*/
@Override
public int hashCode() {
int h = 0, n = size();
final ObjectIterator<Double2ReferenceMap.Entry<V>> i = Double2ReferenceMaps.fastIterator(this);
while (n-- != 0)
h += i.next().hashCode();
return h;
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
final Map<?, ?> m = (Map<?, ?>) o;
if (m.size() != size())
return false;
return double2ReferenceEntrySet().containsAll(m.entrySet());
}
@Override
public String toString() {
final StringBuilder s = new StringBuilder();
final ObjectIterator<Double2ReferenceMap.Entry<V>> i = Double2ReferenceMaps.fastIterator(this);
int n = size();
Double2ReferenceMap.Entry<V> e;
boolean first = true;
s.append("{");
while (n-- != 0) {
if (first)
first = false;
else
s.append(", ");
e = i.next();
s.append(String.valueOf(e.getDoubleKey()));
s.append("=>");
if (this == e.getValue())
s.append("(this map)");
else
s.append(String.valueOf(e.getValue()));
}
s.append("}");
return s.toString();
}
}