nl.basjes.collections.PrefixMap Maven / Gradle / Ivy
Show all versions of prefixmap Show documentation
/*
* Copyright (C) 2018-2020 Niels Basjes
*
* 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
*
* 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.
*/
package nl.basjes.collections;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
*
* An object that maps String prefixes to values.
* A PrefixMap cannot contain duplicate prefixes; each prefix can map to at most one value.
*
*
* The PrefixMap is a key-value type collection where the key is assumed to be the prefix of
* the String for which later an answer is requested.
*
*
* So the retrieval of the value is based on a startsWith() check of the requested input
against each of
* the stored prefixes
. The value associated with the selected prefix is then returned.
*
*
* An example use case is where mobile phone device models of a certain brand all start with
* the same substring. This data structure can be used to efficiently retrieve the best
* fitting prefix to find the associated value (i.e. the brand of the device).
*
* Note that implementations may be constructed to match either case sensitive or case insensitive.
*/
public interface PrefixMap extends Serializable, Map {
/**
* @return the number of prefix-value mappings in this prefixmap
*/
int size();
/**
* @return true if empty.
*/
default boolean isEmpty() {
return size() == 0;
}
/**
* Returns true
if this map contains an exact mapping
* for the specified prefix.
* Note that implementations may be constructed to match either
* case sensitive or case insensitive.
*
* @param prefix prefix whose presence in this prefixmap is to be checked
* @return true
if this map contains an the exact mapping
* for the specified prefix.
*/
boolean containsPrefix(String prefix);
/**
* Copies all of the mappings from the specified map to this prefixmap.
*
* @param prefixesAndValues mappings to be stored in this map
* @throws NullPointerException if one or more of the prefixes or values are null.
* If this happens the PrefixMap is in an undefined state.
*/
default void putAll(Map extends String, ? extends V> prefixesAndValues) {
prefixesAndValues.forEach(this::put);
}
/**
* Stored the specified value as the result for the specified prefix.
* If for the specified prefix previously a value was present then the
* old value is replaced with the new value and the old value is returned.
* Note that implementations may be constructed to store this value for either
* case sensitive or case insensitive matching during retrieval.
*
* @param prefix prefix with which the specified value is to be associated
* @param value value to be associated with the specified prefix
* @return the previous value of the specified prefix
, or
* null
if there was no mapping for prefix
.
* @throws NullPointerException if either the prefix or value are null.
* If this happens the PrefixMap is unchanged.
*/
V put(String prefix, V value);
/**
* Removes the mapping for a prefix if present.
* Note that implementations may be constructed to remove either
* case sensitive (only this exact value) or case insensitive (all case variations).
*
* @param prefix prefix whose mapping is to be removed from the prefixmap
* @return the previous value associated with prefix
(may be null).
* @throws UnsupportedOperationException if not implemented.
*/
default V remove(String prefix) {
throw new UnsupportedOperationException("The 'remove(String prefix)' method has not been implemented in " +
this.getClass().getCanonicalName());
}
@Override
default V remove(Object o) {
throw new UnsupportedOperationException("The 'remove(Object o)' method has not been implemented in " +
this.getClass().getCanonicalName());
}
@Override
default boolean containsKey(Object o) {
throw new UnsupportedOperationException("The 'containsKey(Object o)' method has not been implemented in " +
this.getClass().getCanonicalName());
}
@Override
default boolean containsValue(Object o) {
throw new UnsupportedOperationException("The 'containsValue(Object o)' method has not been implemented in " +
this.getClass().getCanonicalName());
}
/**
* Return the value of the exact
matching prefix.
* The value returned is the stored prefix for which is true:
* input.equals(prefix)
.
* Note that implementations may be constructed to match either
* case sensitive or case insensitive.
*
* @param prefix The string for which we need value of the stored prefix
* @return The value, null if not found.
*/
V get(String prefix);
/**
* Return the value of the exact
matching prefix.
* The value returned is the stored prefix for which is true:
* input.equals(prefix)
.
* Note that implementations may be constructed to match either
* case sensitive or case insensitive.
*
* @param prefix The string for which we need the stored value
* @return The value, null if not found.
*/
@Override
default V get(Object prefix) {
throw new UnsupportedOperationException("The 'get(Object)' method ONLY accepts keys of type String");
}
@Override
default Set keySet() {
throw new UnsupportedOperationException("The 'keySet()' method has not been implemented in " +
this.getClass().getCanonicalName());
}
@Override
default Collection values() {
throw new UnsupportedOperationException("The 'values()' method has not been implemented in " +
this.getClass().getCanonicalName());
}
/**
* The prefixmap will be empty after this call returns.
*
* @throws UnsupportedOperationException if the clear
operation
* is not supported by this map
*/
default void clear() {
throw new UnsupportedOperationException("The 'clear()' method has not been implemented in " +
this.getClass().getCanonicalName());
}
/**
* Return the value of the shortest
matching prefix.
* The value returned is the shortest stored prefix for which is true:
* input.startsWith(prefix)
.
* Note that implementations may be constructed to match either
* case sensitive or case insensitive.
*
* @param input The string for which we need value of the stored prefix
* @return The value, null if not found.
*/
V getShortestMatch(String input);
/**
* Return the value of the longest matching prefix.
* The value returned is the longest stored prefix for which is true:
* input.startsWith(prefix)
.
* Note that implementations may be constructed to match either
* case sensitive or case insensitive.
*
* @param input The string for which we need value of the stored prefix
* @return The value, null if not found.
*/
V getLongestMatch(String input);
}