package it.unimi.dsi.fastutil;

/*
 * 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.
 */


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 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, containsKey(Object) can be used to perform membership queries.

The choice of naming all methods exactly as in Map makes it possible for all type-specific maps to extend type-specific functions (e.g., Int2IntMap extends Int2IntFunction). However, 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 Object2ObjectFunction that can also set its default return value.

Relationship with Function

This interface predates Java 8's Function and it was conceived with a different purpose. To ease interoperability, we extend Function and implement a default method for apply(Object) that delegates to get(Object). However, while the argument of a Function with keys of type T is of type T, the argument of get(Object) is unparameterized (see the example below).

No attempt will be made at creating type-specific versions of Function as the JDK already provides several specializations, such as IntToLongFunction. Rather, type-specific versions of this class do implement the corresponding classes in function: for example, Int2LongFunction extends IntToLongFunction and Int2IntFunction extends IntUnaryOperator. For functions that do not have a corresponding JDK function we extend the closest possible function (widening input and output types): for example, Byte2CharFunction extends IntUnaryOperator.

Default methods and lambda expressions

All optional operations have default methods throwing an UnsupportedOperationException, except for containsKey(Object), which returns true, and size(), which return -1. Thus, it is possible to define an instance of this class using a lambda expression that will specify get(Object). Note that the type signature of get(Object) might lead to slightly counter-intuitive behaviour. For example, to define the identity function on Integer objects you need to write

    it.unimi.dsi.fastutil.Function<Integer, Integer> f = (x) -> (Integer)x;
as the argument to 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 Also:
/** A function mapping keys into values. * * <p>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. * * <p>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). * * <p>Note that there is an {@link it.unimi.dsi.fastutil.objects.Object2ObjectFunction Object2ObjectFunction} that * can also set its default return value. * * <h2>Relationship with {@link java.util.function.Function}</h2> * * <p>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). * * <p>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}. * * <h2>Default methods and lambda expressions</h2> * * <p>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 * <pre> * it.unimi.dsi.fastutil.Function&lt;Integer, Integer&gt; f = (x) -&gt; (Integer)x; * </pre> * as the argument to {@link #get(Object)} is unparameterized. * * <p><strong>Warning</strong>: Equality of functions is <em>not specified</em> * by contract, and it will usually be <em>by reference</em>, 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<K,V> extends java.util.function.Function<K,V> {
{@inheritDoc} This is equivalent to calling get(Object).
Params:
  • key – {@inheritDoc}
See Also:
Returns:{@inheritDoc}
Since:8.0.0
/** {@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).
Params:
  • key – the key.
  • value – the value.
See Also:
Returns:the old value, or null if no value was present for the given 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.
Params:
  • key – the key.
See Also:
Returns:the corresponding value, or null if no value was present for the given key.
/** 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 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.

Params:
  • key – the key.
See Also:
Returns:true if this function associates a value to key.
/** Returns true if this function contains a mapping for the specified key. * * <p>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).
Params:
  • key – the key.
See Also:
Returns:the old value, or null if no value was present for the given key.
/** 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.

/** Returns the intended number of keys in this function, or -1 if no such number exists. * * <p>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 Also:
  • clear.clear()
/** Removes all associations from this function (optional operation). * * @see java.util.Map#clear() */
default void clear() { throw new UnsupportedOperationException(); } }