org.nd4j.common.collection.MultiDimensionalMap Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2015-2018 Skymind, Inc.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available 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.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
package org.nd4j.common.collection;
import org.nd4j.common.primitives.Pair;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;
/**
* Multiple key map
*/
public class MultiDimensionalMap implements Serializable {
private Map, V> backedMap;
/**
* Thread safe sorted map implementation
* @param
* @param
* @param
* @return
*/
public static MultiDimensionalMap newThreadSafeTreeBackedMap() {
return new MultiDimensionalMap<>(new ConcurrentSkipListMap, V>());
}
/**
* Thread safe hash map implementation
* @param
* @param
* @param
* @return
*/
public static MultiDimensionalMap newThreadSafeHashBackedMap() {
return new MultiDimensionalMap<>(new ConcurrentHashMap, V>());
}
/**
* Thread safe hash map impl
* @param
* @param
* @param
* @return
*/
public static MultiDimensionalMap newHashBackedMap() {
return new MultiDimensionalMap<>(new HashMap, V>());
}
/**
* Tree map implementation
* @param
* @param
* @param
* @return
*/
public static MultiDimensionalMap newTreeBackedMap() {
return new MultiDimensionalMap<>(new TreeMap, V>());
}
public MultiDimensionalMap(Map, V> backedMap) {
this.backedMap = backedMap;
}
protected MultiDimensionalMap(){ }
/**
* Returns the number of key-value mappings in this map. If the
* map contains more than Integer.MAX_VALUE elements, returns
* Integer.MAX_VALUE.
*
* @return the number of key-value mappings in this map
*/
public int size() {
return backedMap.size();
}
/**
* Returns true if this map contains no key-value mappings.
*
* @return true if this map contains no key-value mappings
*/
public boolean isEmpty() {
return backedMap.isEmpty();
}
/**
* Returns true if this map contains a mapping for the specified
* key. More formally, returns true if and only if
* this map contains a mapping for a key k such that
* (key==null ? k==null : key.equals(k)). (There can be
* at most one such mapping.)
*
* @param key key whose presence in this map is to be tested
* @return true if this map contains a mapping for the specified
* key
* @throws ClassCastException if the key is of an inappropriate type for
* this map
* (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys
* (optional)
*/
public boolean containsKey(Object key) {
return backedMap.containsKey(key);
}
/**
* Returns true if this map maps one or more keys to the
* specified value. More formally, returns true if and only if
* this map contains at least one mapping to a value v such that
* (value==null ? v==null : value.equals(v)). This operation
* will probably require time linear in the map size for most
* implementations of the Map interface.
*
* @param value value whose presence in this map is to be tested
* @return true if this map maps one or more keys to the
* specified value
* @throws ClassCastException if the value is of an inappropriate type for
* this map
* (optional)
* @throws NullPointerException if the specified value is null and this
* map does not permit null values
* (optional)
*/
public boolean containsValue(Object value) {
return backedMap.containsValue(value);
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* If this map permits null values, then a return value of
* {@code null} does not necessarily indicate that the map
* contains no mapping for the key; it's also possible that the map
* explicitly maps the key to {@code null}. The {@link #containsKey
* containsKey} operation may be used to distinguish these two cases.
*
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or
* {@code null} if this map contains no mapping for the key
* @throws ClassCastException if the key is of an inappropriate type for
* this map
* (optional)
* @throws NullPointerException if the specified key is null and this map
* does not permit null keys
* (optional)
*/
public V get(Object key) {
return backedMap.get(key);
}
/**
* Associates the specified value with the specified key in this map
* (optional operation). If the map previously contained a mapping for
* the key, the old value is replaced by the specified value. (A map
* m is said to contain a mapping for a key k if and only
* if {@link #containsKey(Object) m.containsKey(k)} would return
* true.)
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with key, or
* null if there was no mapping for key.
* (A null return can also indicate that the map
* previously associated null with key,
* if the implementation supports null values.)
* @throws UnsupportedOperationException if the put operation
* is not supported by this map
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
* @throws NullPointerException if the specified key or value is null
* and this map does not permit null keys or values
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
*/
public V put(Pair key, V value) {
return backedMap.put(key, value);
}
/**
* Removes the mapping for a key from this map if it is present
* (optional operation). More formally, if this map contains a mapping
* from key k to value v such that
* (key==null ? k==null : key.equals(k))
, that mapping
* is removed. (The map can contain at most one such mapping.)
*
* Returns the value to which this map previously associated the key,
* or null if the map contained no mapping for the key.
*
* If this map permits null values, then a return value of
* null does not necessarily indicate that the map
* contained no mapping for the key; it's also possible that the map
* explicitly mapped the key to null.
*
* The map will not contain a mapping for the specified key once the
* call returns.
*
* @param key key whose mapping is to be removed from the map
* @return the previous value associated with key, or
* null if there was no mapping for key.
* @throws UnsupportedOperationException if the remove operation
* is not supported by this map
* @throws ClassCastException if the key is of an inappropriate type for
* this map
* (optional)
* @throws NullPointerException if the specified key is null and this
* map does not permit null keys
* (optional)
*/
public V remove(Object key) {
return backedMap.remove(key);
}
/**
* Copies all of the mappings from the specified map to this map
* (optional operation). The effect of this call is equivalent to that
* of calling {@link Map<>#put(k, v)} on this map once
* for each mapping from key k to value v in the
* specified map. The behavior of this operation is undefined if the
* specified map is modified while the operation is in progress.
*
* @param m mappings to be stored in this map
* @throws UnsupportedOperationException if the putAll operation
* is not supported by this map
* @throws ClassCastException if the class of a key or value in the
* specified map prevents it from being stored in this map
* @throws NullPointerException if the specified map is null, or if
* this map does not permit null keys or values, and the
* specified map contains null keys or values
* @throws IllegalArgumentException if some property of a key or value in
* the specified map prevents it from being stored in this map
*/
public void putAll(Map extends Pair, ? extends V> m) {
backedMap.putAll(m);
}
/**
* Removes all of the mappings from this map (optional operation).
* The map will be empty after this call returns.
*
* @throws UnsupportedOperationException if the clear operation
* is not supported by this map
*/
public void clear() {
backedMap.clear();
}
/**
* Returns a {@link Set} view of the keys contained in this map.
* The applyTransformToDestination is backed by the map, so changes to the map are
* reflected in the applyTransformToDestination, and vice-versa. If the map is modified
* while an iteration over the applyTransformToDestination is in progress (except through
* the iterator's own remove operation), the results of
* the iteration are undefined. The applyTransformToDestination supports element removal,
* which removes the corresponding mapping from the map, via the
* Iterator.remove, Set.remove,
* removeAll, retainAll, and clear
* operations. It does not support the add or addAll
* operations.
*
* @return a applyTransformToDestination view of the keys contained in this map
*/
public Set> keySet() {
return backedMap.keySet();
}
/**
* Returns a {@link Collection} view of the values contained in this map.
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. If the map is
* modified while an iteration over the collection is in progress
* (except through the iterator's own remove operation),
* the results of the iteration are undefined. The collection
* supports element removal, which removes the corresponding
* mapping from the map, via the Iterator.remove,
* Collection.remove, removeAll,
* retainAll and clear operations. It does not
* support the add or addAll operations.
*
* @return a collection view of the values contained in this map
*/
public Collection values() {
return backedMap.values();
}
/**
* Returns a {@link Set} view of the mappings contained in this map.
* The applyTransformToDestination is backed by the map, so changes to the map are
* reflected in the applyTransformToDestination, and vice-versa. If the map is modified
* while an iteration over the applyTransformToDestination is in progress (except through
* the iterator's own remove operation, or through the
* setValue operation on a map entry returned by the
* iterator) the results of the iteration are undefined. The applyTransformToDestination
* supports element removal, which removes the corresponding
* mapping from the map, via the Iterator.remove,
* Set.remove, removeAll, retainAll and
* clear operations. It does not support the
* add or addAll operations.
*
* @return a applyTransformToDestination view of the mappings contained in this map
*/
public Set> entrySet() {
Set> ret = new HashSet<>();
for (Pair pair : backedMap.keySet()) {
ret.add(new Entry<>(pair.getFirst(), pair.getSecond(), backedMap.get(pair)));
}
return ret;
}
public V get(K k, T t) {
return get(new Pair<>(k, t));
}
public void put(K k, T t, V v) {
put(new Pair<>(k, t), v);
}
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof MultiDimensionalMap))
return false;
MultiDimensionalMap that = (MultiDimensionalMap) o;
return !(backedMap != null ? !backedMap.equals(that.backedMap) : that.backedMap != null);
}
public int hashCode() {
return backedMap != null ? backedMap.hashCode() : 0;
}
public String toString() {
return "MultiDimensionalMap{" + "backedMap=" + backedMap + '}';
}
public boolean contains(K k, T t) {
return containsKey(new Pair<>(k, t));
}
public static class Entry implements Map.Entry, V> {
private K firstKey;
private T secondKey;
private V value;
public Entry(K firstKey, T secondKey, V value) {
this.firstKey = firstKey;
this.secondKey = secondKey;
this.value = value;
}
public K getFirstKey() {
return firstKey;
}
public void setFirstKey(K firstKey) {
this.firstKey = firstKey;
}
public T getSecondKey() {
return secondKey;
}
public void setSecondKey(T secondKey) {
this.secondKey = secondKey;
}
public V getValue() {
return value;
}
/**
* Replaces the value corresponding to this entry with the specified
* value (optional operation). (Writes through to the map.) The
* behavior of this call is undefined if the mapping has already been
* removed from the map (by the iterator's remove operation).
*
* @param value new value to be stored in this entry
* @return old value corresponding to the entry
* @throws UnsupportedOperationException if the put operation
* is not supported by the backing map
* @throws ClassCastException if the class of the specified value
* prevents it from being stored in the backing map
* @throws NullPointerException if the backing map does not permit
* null values, and the specified value is null
* @throws IllegalArgumentException if some property of this value
* prevents it from being stored in the backing map
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
public V setValue(V value) {
V old = this.value;
this.value = value;
return old;
}
/**
* Returns the key corresponding to this entry.
*
* @return the key corresponding to this entry
* @throws IllegalStateException implementations may, but are not
* required to, throw this exception if the entry has been
* removed from the backing map.
*/
public Pair getKey() {
return new Pair<>(firstKey, secondKey);
}
}
}