it.unimi.dsi.fastutil.Function Maven / Gradle / Ivy
Show all versions of fastutil-core Show documentation
/*
* Copyright (C) 2002-2024 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;
import java.util.function.IntToLongFunction;
import java.util.function.IntUnaryOperator;
import it.unimi.dsi.fastutil.bytes.Byte2CharFunction;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.ints.Int2LongFunction;
/** A function mapping keys into values.
*
* Instances of this class represent functions: the main difference with {@link java.util.Map}
* is that functions do not in principle allow enumeration of their domain or range. The need for
* this interface lies in the existence of several highly optimized implementations of
* functions (e.g., minimal perfect hashes) which do not actually store their domain or range explicitly.
* In case the domain is known, {@link #containsKey(Object)} can be used to perform membership queries.
*
*
The choice of naming all methods exactly as in {@link java.util.Map} makes it possible
* for all type-specific maps to extend type-specific functions (e.g., {@link it.unimi.dsi.fastutil.ints.Int2IntMap Int2IntMap}
* extends {@link it.unimi.dsi.fastutil.ints.Int2IntFunction Int2IntFunction}). However, {@link #size()} is allowed to return -1 to denote
* that the number of keys is not available (e.g., in the case of a string hash function).
*
*
Note that there is an {@link it.unimi.dsi.fastutil.objects.Object2ObjectFunction Object2ObjectFunction} that
* can also set its default return value.
*
*
Relationship with {@link java.util.function.Function}
*
* This interface predates Java 8's {@link java.util.function.Function} and it was conceived with
* a different purpose. To ease interoperability, we extend {@link java.util.function.Function} and
* implement a default method for {@link #apply(Object)} that delegates to {@link #get(Object)}. However,
* while the argument of a {@link java.util.function.Function} with keys of type {@code T} is of type
* {@code T}, the argument of {@link #get(Object)} is unparameterized (see the example below).
*
*
No attempt will be made at creating type-specific versions of {@link java.util.function.Function} as
* the JDK already provides several specializations, such as {@link IntToLongFunction}.
* Rather, type-specific versions of this class do implement the corresponding classes in {@link java.util.function}:
* for example, {@link Int2LongFunction} extends {@link IntToLongFunction} and {@link Int2IntFunction} extends
* {@link IntUnaryOperator}. For functions that do not have a corresponding JDK function we extend the
* closest possible function (widening input and output types): for example, {@link Byte2CharFunction} extends
* {@link IntUnaryOperator}.
*
*
Default methods and lambda expressions
*
* All optional operations have default methods throwing an {@link UnsupportedOperationException}, except
* for {@link #containsKey(Object)}, which returns true, and {@link #size()}, which return -1.
* Thus, it is possible to define an instance of this class using a lambda expression that will specify
* {@link #get(Object)}. Note that the type signature of {@link #get(Object)} might lead to slightly
* counter-intuitive behaviour. For example, to define the identity function on {@link Integer} objects
* you need to write
*
* it.unimi.dsi.fastutil.Function<Integer, Integer> f = (x) -> (Integer)x;
*
* as the argument to {@link #get(Object)} is unparameterized.
*
* Warning: Equality of functions is not specified
* by contract, and it will usually be by reference, as there is no way to enumerate the keys
* and establish whether two functions represent the same mathematical entity.
*
* @see java.util.Map
* @see java.util.function.Function
*/
@FunctionalInterface
public interface Function extends java.util.function.Function {
/** {@inheritDoc} This is equivalent to calling {@link #get(Object)}.
*
* @param key {@inheritDoc}
* @return {@inheritDoc}
* @see java.util.function.Function#apply(Object)
* @see #get(Object)
* @since 8.0.0
*/
@Override
default V apply(final K key) {
return get(key);
}
/** Associates the specified value with the specified key in this function (optional operation).
*
* @param key the key.
* @param value the value.
* @return the old value, or {@code null} if no value was present for the given key.
* @see java.util.Map#put(Object,Object)
*/
default V put(final K key, final V value) {
throw new UnsupportedOperationException();
}
/** Returns the value associated by this function to the specified key.
*
* @param key the key.
* @return the corresponding value, or {@code null} if no value was present for the given key.
* @see java.util.Map#get(Object)
*/
V get(Object key);
/**
* Returns the value associated by this function to the specified key, or give the specified
* value if not present.
*
* @param key the key.
* @param defaultValue the default value to return if not present.
* @return the corresponding value, or {@code defaultValue} if no value was present for the
* given key.
* @see java.util.Map#getOrDefault(Object, Object)
* @since 8.5.0
*/
default V getOrDefault(final Object key, final V defaultValue) {
final V value = get(key);
return (value != null || containsKey(key)) ? value : defaultValue;
}
/** Returns true if this function contains a mapping for the specified key.
*
* Note that for some kind of functions (e.g., hashes) this method
* will always return true. This default implementation, in particular,
* always return true.
*
* @param key the key.
* @return true if this function associates a value to {@code key}.
* @see java.util.Map#containsKey(Object)
*/
default boolean containsKey(final Object key) {
return true;
}
/** Removes this key and the associated value from this function if it is present (optional operation).
*
* @param key the key.
* @return the old value, or {@code null} if no value was present for the given key.
* @see java.util.Map#remove(Object)
*/
default V remove(final Object key) {
throw new UnsupportedOperationException();
}
/** Returns the intended number of keys in this function, or -1 if no such number exists.
*
*
Most function implementations will have some knowledge of the intended number of keys
* in their domain. In some cases, however, this might not be possible. This default
* implementation, in particular, returns -1.
*
* @return the intended number of keys in this function, or -1 if that number is not available.
*/
default int size() {
return -1;
}
/** Removes all associations from this function (optional operation).
*
* @see java.util.Map#clear()
*/
default void clear() {
throw new UnsupportedOperationException();
}
}