Java.Java8.What are the functional interfaces of the form _To_Function?

Java has a set of primitive-specialized functional interfaces of the form:

XToYFunction

These are used to convert from one primitive (or boxed) type to another efficiently — avoiding boxing and unboxing.

🔧 General Pattern

interface XToYFunction {
    Y applyAsY(X value);
}

Where:

  • X and Y are primitive types like int, long, double
  • These interfaces live in java.util.function
  • They are designed to work more efficiently with primitives

✅ Common _To_ Function Interfaces

InterfaceInput TypeReturn TypeExample Use Case
IntToLongFunctionintlong(int x) -> (long) x * 1000L
IntToDoubleFunctionintdouble(int x) -> Math.sqrt(x)
LongToIntFunctionlongint(long x) -> (int)(x % 100)
LongToDoubleFunctionlongdouble(long x) -> (double) x / 2.0
DoubleToIntFunctiondoubleint(double d) -> (int) Math.floor(d)
DoubleToLongFunctiondoublelong(double d) -> Math.round(d)
ToIntFunction<T>TintString::length
ToLongFunction<T>Tlong(String s) -> s.length() * 1000L
ToDoubleFunction<T>Tdouble(String s) -> s.length() * 0.5

🧠 Examples

IntToDoubleFunction sqrt = x -> Math.sqrt(x);
System.out.println(sqrt.applyAsDouble(9)); // Output: 3.0
ToIntFunction<String> length = String::length;
System.out.println(length.applyAsInt("Hello")); // Output: 5
DoubleToLongFunction round = Math::round;
System.out.println(round.applyAsLong(2.7)); // Output: 3

✅ Summary

These interfaces are:

  • Efficient: avoid boxing (Integer, Double, etc.)
  • Clear in intent: show exactly what’s being converted
  • Useful for data transformation in streams and calculations

🎯 Why Were These Interfaces Created?

1. Performance: Avoid Autoboxing

Java generics don’t support primitives (e.g., you can’t do Function<int, int>), so when you use Function<Integer, Integer>, Java autoboxes the int to Integer — which:

  • Creates temporary heap objects (Integer instead of raw int)
  • Hurts performance in tight loops or big streams

Solution: Introduce primitive-specialized functional interfaces like:

  • IntFunction<R>, ToIntFunction<T>
  • IntToDoubleFunction, DoubleToLongFunction

→ These work directly with primitives, no boxing involved.


2. Cleaner Code for Primitive Operations

Imagine this:

Function<Integer, Double> sqrt = x -> Math.sqrt(x);

Better

IntToDoubleFunction sqrt = x -> Math.sqrt(x);

This is faster and shows intent more clearly: I’m working with primitive int and returning a double.

3. Stream API Compatibility

When you work with primitive streams (IntStream, LongStream, DoubleStream), they require primitive functional interfaces.

For example:

IntStream.range(1, 5)
         .mapToDouble(x -> Math.pow(x, 2))  // Needs IntToDoubleFunction
         .forEach(System.out::println);

You can’t use Function<Integer, Double> here — it would crash or box, defeating the purpose.


📍 Where Should You Use Them?

✅ 1. In Primitive Streams (IntStream, LongStream, DoubleStream)

IntToDoubleFunction toSqrt = Math::sqrt;
IntStream.of(1, 4, 9)
         .mapToDouble(toSqrt)
         .forEach(System.out::println);

✅ 2. In High-performance numeric code

Anywhere you process a lot of numbers (e.g., sensor data, financial calculations, image processing), avoiding boxing matters.

DoubleToIntFunction discretizer = d -> (int)(d * 100);

✅ 3. When You Want to Be Explicit & Intentional

  • ToIntFunction<String> length = String::length; — very readable
  • Clearer than Function<String, Integer> and faster

🧠 Summary

ReasonExplanation
✅ Avoid boxingNo Integer, Double heap objects — better performance
✅ Work with primitive streamsStream API requires these for IntStream, LongStream, DoubleStream
✅ More readable codeMakes it clear you’re converting between primitive types
This entry was posted in Без рубрики. Bookmark the permalink.