How do I use the LongUnaryOperator functional interface in Java?

Key Features of LongUnaryOperator

  • It performs operations on long values.
  • It has a single abstract method: long applyAsLong(long operand), which takes one long argument and returns a long result.
  • Additional default and static methods such as andThen() and compose() allow chaining of operations.

Key Methods in LongUnaryOperator

  1. long applyAsLong(long operand)
    • Performs the operation and returns the result.
  2. andThen(LongUnaryOperator after)
    • Returns a composed LongUnaryOperator that applies the current operation, then applies the specified LongUnaryOperator operation.
  3. compose(LongUnaryOperator before)
    • Returns a composed LongUnaryOperator that applies the given operation first, and then the current operation.
  4. static LongUnaryOperator identity()
    • Returns a LongUnaryOperator that returns the input value as-is (acts as an identity function).

Using LongUnaryOperator in Practice

1. Basic Example

Here is a simple example where we use LongUnaryOperator to create a lambda that doubles a number:

package org.kodejava.util.function;

import java.util.function.LongUnaryOperator;

public class LongUnaryOperatorExample {
   public static void main(String[] args) {
      // Lambda to double the value
      LongUnaryOperator doubleValue = operand -> operand * 2;

      long input = 5L;
      // Apply the operation
      long result = doubleValue.applyAsLong(input);
      System.out.println("Result: " + result);
      // Output: 10
   }
}

2. Using Method References

We can use method references to refer to a static or instance method that matches the functional signature:

package org.kodejava.util.function;

import java.util.function.LongUnaryOperator;

public class LongUnaryOperatorMethodRef {
   public static long square(long x) {
      return x * x;
   }

   public static void main(String[] args) {
      // Method reference
      LongUnaryOperator squareOperator = LongUnaryOperatorMethodRef::square;

      long input = 6L;
      // Apply the operation
      long result = squareOperator.applyAsLong(input);
      System.out.println("Result: " + result);
      // Output: 36
   }
}

3. Chaining Operations

The andThen() and compose() methods can be used to chain operations sequentially.

  • andThen(): Executes the current operation first, then the next operation.
  • compose(): Executes the given operation first, then the current operation.

Example:

package org.kodejava.util.function;

import java.util.function.LongUnaryOperator;

public class LongUnaryOperatorChaining {
   public static void main(String[] args) {
      LongUnaryOperator increment = operand -> operand + 1;
      LongUnaryOperator square = operand -> operand * operand;

      // Chain operations: (increment -> square)
      LongUnaryOperator incrementThenSquare = increment.andThen(square);

      long input = 3L;
      // (3 + 1)^2 = 16
      long result1 = incrementThenSquare.applyAsLong(input);
      System.out.println("Increment then Square Result: " + result1);

      // Chain operations: (increment -> square)
      LongUnaryOperator incrementComposeSquare = square.compose(increment);

      // (3 + 1)^2 = 16
      long result2 = incrementComposeSquare.applyAsLong(input);
      System.out.println("Increment compose Increment Result: " + result2);
   }
}

4. Using with Streams

The LongUnaryOperator can also be used in contexts like streams, especially LongStream:

package org.kodejava.util.function;

import java.util.stream.LongStream;
import java.util.function.LongUnaryOperator;

public class LongUnaryOperatorWithStreams {
   public static void main(String[] args) {
      LongUnaryOperator multiplyByThree = operand -> operand * 3;

      LongStream numbers = LongStream.of(1L, 2L, 3L, 4L);
      numbers.map(multiplyByThree).forEach(System.out::println);
      // Output:
      // 3
      // 6
      // 9
      // 12
   }
}

5. Example of identity():

package org.kodejava.util.function;

import java.util.function.LongUnaryOperator;

public class LongUnaryOperatorIdentity {
   public static void main(String[] args) {
      LongUnaryOperator identity = LongUnaryOperator.identity();

      long input = 25L;
      // Input and output are the same
      long result = identity.applyAsLong(input);
      System.out.println("Identity Result: " + result);
      // Output: 25
   }
}

Summary

The LongUnaryOperator is a useful functional interface for performing operations on long values. It is commonly applied for transformations in data processing workflows, functional programming, and stream pipelines. Its ability to compose and chain operations allows for clean and concise code.

How do I use the LongToIntFunction functional interface in Java?

The LongToIntFunction is a functional interface in Java located in the java.util.function package. It represents a function that accepts a long-valued argument and produces an int-valued result. It is a specialized form of functional interface primarily used to avoid boxing when working with primitive types.

Here is a guide on how to use the LongToIntFunction interface:

1. Functional Interface Definition

The LongToIntFunction is defined as:

@FunctionalInterface
public interface LongToIntFunction {
    int applyAsInt(long value);
}

This means:
– It has a single abstract method named applyAsInt(long value), which takes a long as input and returns an int.
– It can be implemented using a lambda expression, method reference, or an anonymous class.


2. Usage Examples

a. Using Lambda Expression:

package org.kodejava.util.function;

import java.util.function.LongToIntFunction;

public class LongToIntFunctionExample {
    public static void main(String[] args) {
        // Example: Converting long to int (e.g., modulo operation)
        // Converts and limits to two-digit values
        LongToIntFunction longToInt = value -> (int) (value % 100);

        long exampleValue = 12345678L;
        int result = longToInt.applyAsInt(exampleValue);

        System.out.println("Result: " + result);
        // Output: 78
    }
}

In this example, the lambda expression converts a long value into an int by taking its modulo.


b. Using Method Reference:

If there’s an existing method compatible with the signature of applyAsInt(long value), we can use a method reference.

package org.kodejava.util.function;

import java.util.function.LongToIntFunction;

public class LongToIntFunctionExample2 {
    public static void main(String[] args) {
        // Example: Using a method reference for a custom conversion
        LongToIntFunction longToInt = LongToIntFunctionExample2::convertLongToInt;

        long exampleValue = 987654321L;
        int result = longToInt.applyAsInt(exampleValue);

        // Custom behavior
        System.out.println("Result: " + result);
    }

    // Custom method matching the LongToIntFunction signature
    public static int convertLongToInt(long value) {
        // Keep the last 3 digits as int
        return (int) (value % 1000);
    }
}

c. Using an Anonymous Class:

We can also use an anonymous class to implement the interface.

package org.kodejava.util.function;

import java.util.function.LongToIntFunction;

public class LongToIntFunctionExample3 {
    public static void main(String[] args) {
        // Anonymous class implementation
        LongToIntFunction longToInt = new LongToIntFunction() {
            @Override
            public int applyAsInt(long value) {
                return (int) (value / 1000);
            }
        };

        long exampleValue = 987654321L;
        int result = longToInt.applyAsInt(exampleValue);

        System.out.println("Result: " + result);
        // Output: 987654
    }
}

3. When to Use

The LongToIntFunction is useful when:
– We work with primitive types (long and int) and want to avoid the unnecessary cost of boxing and unboxing.
– We need to process a long and get an int result in a concise, functional programming style.


4. Real-life Scenario

Imagine we are working with a large dataset containing timestamps represented as long values. We may want to extract part of the timestamp (like the hour or day) as an int:

package org.kodejava.util.function;

import java.time.Instant;
import java.util.function.LongToIntFunction;

public class LongToIntFunctionExample4 {
    public static void main(String[] args) {
        // Extract the hour part from a UNIX timestamp
        LongToIntFunction extractHour =
                timestamp -> Instant.ofEpochSecond(timestamp)
                        .atZone(java.time.ZoneId.systemDefault()).getHour();

        // Current timestamp in seconds
        long currentTimestamp = Instant.now().getEpochSecond();
        int hour = extractHour.applyAsInt(currentTimestamp);

        System.out.println("Current Hour: " + hour);
    }
}

This shows how we can use LongToIntFunction in a practical application.


Summary

  • The LongToIntFunction interface makes it easy to handle the transformation from long to int type.
  • It avoids overhead caused by boxing and unboxing of primitive types.
  • It is often used with lambda expressions, method references, or anonymous classes.

How do I use the LongToDoubleFunction functional interface in Java?

The LongToDoubleFunction is a functional interface in Java that belongs to the java.util.function package. It represents a function that accepts a long value as an argument and produces a result of type double. This functional interface is typically used in scenarios where we want to perform an operation that converts a long input into a double output without having to box or unbox objects.

Here’s how we can use the LongToDoubleFunction interface:

1. Structure of the Interface

The LongToDoubleFunction interface has a single abstract method:

@FunctionalInterface
public interface LongToDoubleFunction {
    double applyAsDouble(long value);
}

This method, applyAsDouble, takes a long as input and returns a double.


2. Example Usage

Example 1: Using a Lambda Expression

We can use a lambda expression to implement the applyAsDouble method:

package org.kodejava.util.function;

import java.util.function.LongToDoubleFunction;

public class LongToDoubleFunctionExample {
    public static void main(String[] args) {
        // Example 1: Convert a long to a double (e.g., divide by 2.5)
        LongToDoubleFunction longToDouble = (value) -> value / 2.5;

        long input = 10L;
        double result = longToDouble.applyAsDouble(input);

        System.out.println("Input: " + input);
        System.out.println("Result: " + result);
    }
}

Output:

Input: 10
Result: 4.0

Example 2: Referencing a Method

We can also use a method reference if we have a method that matches the signature of applyAsDouble.

package org.kodejava.util.function;

import java.util.function.LongToDoubleFunction;

public class LongToDoubleFunctionExample2 {
    public static void main(String[] args) {
        LongToDoubleFunction convertToDouble = LongToDoubleFunctionExample2::convert;

        long input = 15L;
        double result = convertToDouble.applyAsDouble(input);

        System.out.println("Input: " + input);
        System.out.println("Result: " + result);
    }

    public static double convert(long value) {
        return value * 1.2; // Example logic
    }
}

Output:

Input: 15
Result: 18.0

3. Practical Use Cases

  • Mathematical Calculations: Converting long values (like IDs or timestamps) into floating-point representations for calculations.
  • Unit Conversion: Transforming a value in one unit (e.g., seconds as a long) to another (e.g., minutes as a double).
  • Stream API: We can use LongToDoubleFunction with streams, such as LongStream, for functional programming.

Example 3: Using with Streams

package org.kodejava.util.function;

import java.util.function.LongToDoubleFunction;
import java.util.stream.LongStream;

public class LongToDoubleFunctionExample3 {
    public static void main(String[] args) {
        LongToDoubleFunction divideByPi = (value) -> value / Math.PI;

        LongStream.of(10L, 20L, 30L)
                .mapToDouble(divideByPi) // Map each long to a double
                .forEach(System.out::println); // Print each result
    }
}

Output:

3.183098861837907
6.366197723675814
9.549296585513721

4. Key Points

  • It is one of the specialized functional interfaces in Java (LongToIntFunction, DoubleToLongFunction, etc.) to avoid boxing overhead.
  • It is a functional interface, so we can use it with lambda expressions, method references, or anonymous classes.
  • Commonly used with streams for functional-style processing of numbers.

How do I use the LongSupplier functional interface in Java?

The LongSupplier is a functional interface in Java that is part of the java.util.function package. It represents a function that supplies a long-valued result. This interface is particularly useful when we need to generate or provide long values without requiring input arguments.

Since LongSupplier is a functional interface, it has a single abstract method:

  • long getAsLong(): This method is used to return a long value.

Here is how we can use the LongSupplier interface in Java:


Example 1: Basic Usage with Lambda Expression

package org.kodejava.util.function;

import java.util.function.LongSupplier;

public class LongSupplierExample {
    public static void main(String[] args) {
        // Using a LongSupplier to provide the current system time in milliseconds
        LongSupplier currentTimeSupplier = () -> System.currentTimeMillis();

        // Getting a long value
        long currentTime = currentTimeSupplier.getAsLong();
        System.out.println("Current Time in Milliseconds: " + currentTime);
    }
}

Example 2: Using Method References

We can also use method references instead of a lambda if it matches the expected signature of the LongSupplier.

package org.kodejava.util.function;

import java.util.function.LongSupplier;

public class LongSupplierExample2 {
    public static void main(String[] args) {
        // Using method reference
        LongSupplier nanoTimeSupplier = System::nanoTime;

        // Getting a long value
        long nanoTime = nanoTimeSupplier.getAsLong();
        System.out.println("Current Time in Nanoseconds: " + nanoTime);
    }
}

Example 3: Custom Implementation

We can create our own implementation of LongSupplier.

package org.kodejava.util.function;

import java.util.function.LongSupplier;

public class LongSupplierExample3 {
    public static void main(String[] args) {
        // Custom implementation
        LongSupplier randomLongSupplier = new LongSupplier() {
            @Override
            public long getAsLong() {
                // Generate a random long value
                return (long) (Math.random() * 1000);
            }
        };

        // Getting a long value
        long randomValue = randomLongSupplier.getAsLong();
        System.out.println("Random Long Value: " + randomValue);
    }
}

Example 4: Using with Streams

LongSupplier can also be useful when used with streams for generating a sequence of long values.

package org.kodejava.util.function;

import java.util.function.LongSupplier;
import java.util.stream.LongStream;

public class LongSupplierExample4 {
    public static void main(String[] args) {
        // LongSupplier to generate an infinite series of long values
        LongSupplier supplier = new LongSupplier() {
            private long start = 1;

            @Override
            public long getAsLong() {
                return start++;
            }
        };

        // Using the LongSupplier with LongStream.generate
        LongStream.generate(supplier)
                .limit(10) // Limit to 10 values
                .forEach(System.out::println); // Print each value
    }
}

Key Points:

  1. LongSupplier is a no-argument functional interface that always returns a long value.
  2. It is lightweight and simple to use with lambdas, method references, or custom implementations.
  3. Useful in scenarios where we need to continuously or repeatedly generate long values, such as timestamps, counters, or random numbers.

How do I use the LongPredicate functional interface in Java?

In Java, the LongPredicate is a functional interface introduced in Java 8 as part of the java.util.function package. It represents a predicate (a boolean-valued function) that takes a single long value as its input argument.

The key method in LongPredicate is:

boolean test(long value);

Here’s how we can use the LongPredicate functional interface:

Example Usage of LongPredicate

1. Basic Example with Lambda Expression:

package org.kodejava.util.function;

import java.util.function.LongPredicate;

public class LongPredicateExample {
   public static void main(String[] args) {
      // Define a LongPredicate to check if a number is even
      LongPredicate isEven = value -> value % 2 == 0;

      long number = 10;

      // Use the LongPredicate
      if (isEven.test(number)) {
         System.out.println(number + " is even.");
      } else {
         System.out.println(number + " is odd.");
      }
   }
}

2. Combining LongPredicates Using and, or, and negate:

package org.kodejava.util.function;

import java.util.function.LongPredicate;

public class LongPredicateExample2 {
   public static void main(String[] args) {
      // Define two LongPredicates: even and greater than 5
      LongPredicate isEven = value -> value % 2 == 0;
      LongPredicate isGreaterThanFive = value -> value > 5;

      long number = 10;

      // Combine using 'and'
      LongPredicate isEvenAndGreaterThanFive = isEven.and(isGreaterThanFive);
      System.out.println("Is " + number + " even and greater than 5? " +
                         isEvenAndGreaterThanFive.test(number)); // true

      // Combine using 'or'
      LongPredicate isEvenOrGreaterThanFive = isEven.or(isGreaterThanFive);
      System.out.println("Is " + number + " even or greater than 5? " +
                         isEvenOrGreaterThanFive.test(number)); // true

      // Negate the 'isEven' predicate
      LongPredicate isOdd = isEven.negate();
      System.out.println("Is " + number + " odd? " + isOdd.test(number)); // false
   }
}

3. Using with Streams (e.g., LongStream):

If we use the LongPredicate with streams, it can be helpful for filtering LongStream.

package org.kodejava.util.function;

import java.util.function.LongPredicate;
import java.util.stream.LongStream;

public class LongPredicateWithStreams {
   public static void main(String[] args) {
      // Generate a stream of numbers from 1 to 10
      LongStream stream = LongStream.rangeClosed(1, 10);

      // Define a LongPredicate to filter even numbers
      LongPredicate isEven = value -> value % 2 == 0;

      // Use 'filter' with LongPredicate
      stream.filter(isEven)
              .forEach(System.out::println); // Prints 2, 4, 6, 8, 10
   }
}

4. Method Reference with LongPredicate:

We can also use method references if we have a method that matches the signature of the test method:

package org.kodejava.util.function;

import java.util.function.LongPredicate;

public class LongPredicateMethodReference {
   public static void main(String[] args) {
      LongPredicate isPositive = LongPredicateMethodReference::isPositive;

      long number = 5;
      // true
      System.out.println("Is " + number + " positive? " + isPositive.test(number));
   }

   // Method to check if a number is positive
   public static boolean isPositive(long value) {
      return value > 0;
   }
}

Key Points about LongPredicate

  • The functional method in LongPredicate is boolean test(long value). This method evaluates the predicate against the given long value and returns a boolean result.
  • It is often used in lambda expressions or method references.
  • We can combine multiple LongPredicate instances using and, or, and negate methods.

Summary

  • Use LongPredicate when working with primitive long arguments in functional programming scenarios.
  • It helps to avoid boxing overhead compared to Predicate<Long>.
  • We can define simple or complex conditions, combine predicates using and, or, and negate, and use them with streams for concise and readable code.

How do I use the LongFunction functional interface in Java?

The LongFunction is a functional interface in Java present in the java.util.function package. It represents a function that takes a long as input and produces a result of a specified type.

Key points about LongFunction:

1. Single Abstract Method:

It contains a single abstract method:

R apply(long value);

Here, R is the return type of the function.

2. Functional Interface:

As a functional interface, it can be used with lambda expressions, method references, or anonymous classes.


Usage of LongFunction

We use LongFunction when we want to process a long value and return a result of a specific type.

Example 1: Simple Lambda Expression

Here’s an example where we convert a long to its string representation:

package org.kodejava.util.function;

import java.util.function.LongFunction;

public class LongFunctionExample {
   public static void main(String[] args) {
      // Create a LongFunction that converts long to String
      LongFunction<String> longToString = (long value) -> "Value: " + value;

      // Apply the function
      String result = longToString.apply(25L);
      System.out.println(result);
      // Output: Value: 25
   }
}

Example 2: Use with Streams

We can use LongFunction with streams, especially when working with LongStream.

package org.kodejava.util.function;

import java.util.function.LongFunction;
import java.util.stream.LongStream;

public class LongFunctionWithStream {
   public static void main(String[] args) {
      // Create a LongFunction that converts a long to its square formatted as a String
      LongFunction<String> longToSquareString =
              (long value) -> "Square of " + value + " is " + (value * value);

      // Use it in a LongStream
      LongStream.range(1, 5)
              .mapToObj(longToSquareString)
              .forEach(System.out::println);
   }
}

Output:

Square of 1 is 1
Square of 2 is 4
Square of 3 is 9
Square of 4 is 16

Example 3: Using a Method Reference

We can use method references with LongFunction as well. For instance:

package org.kodejava.util.function;

import java.util.function.LongFunction;

public class LongFunctionMethodReference {
   public static void main(String[] args) {
      // Method reference for a custom static method
      LongFunction<String> longToString = LongFunctionMethodReference::customFormatter;

      // Apply the function
      System.out.println(longToString.apply(26L));
      // Output: Custom Value: 26
   }

   // Custom static method
   public static String customFormatter(long value) {
      return "Custom Value: " + value;
   }
}

Practical Use Cases

Some scenarios where LongFunction can be useful:
1. Transforming numerical IDs: Converting long IDs (e.g., user or record IDs) into their string descriptions.
2. Processing large numerical data: When working with LongStream, LongFunction can help in transforming long values into complex objects.
3. Mapping long values to specific results: E.g., mapping employee IDs to employee details.


Summary

LongFunction is a versatile functional interface designed for processing long inputs and returning a result of any type. It can be easily used in conjunction with lambdas, method references, and streams to write compact and expressive code.

How do I use the LongConsumer functional interface in Java?

The LongConsumer functional interface in Java is part of the java.util.function package and is commonly used for defining operations that consume a single long-valued argument and return no result. It’s a specialization of Consumer for the long primitive type.

The key method in LongConsumer is:

void accept(long value);

Using LongConsumer

Here’s how we can use the LongConsumer functional interface:

  1. Lambda Example: We can use a lambda expression to define the action for accept.
  2. Method Reference: We can pass a method reference as a LongConsumer.
  3. Combine Consumers: We can use the andThen method to chain multiple LongConsumer instances together.

Example 1: Using a Lambda Expression

package org.kodejava.util.function;

import java.util.function.LongConsumer;

public class LongConsumerExample {
    public static void main(String[] args) {
        LongConsumer printLong = value -> System.out.println("Value: " + value);

        // Calling the accept method
        printLong.accept(42L);
        // Output: Value: 42
    }
}

Example 2: Method Reference

We can also use a method reference if we already have a method that accepts a long and performs an operation.

package org.kodejava.util.function;

import java.util.function.LongConsumer;

public class LongConsumerMethodRef {
    public static void main(String[] args) {
        LongConsumer printLong = System.out::println;

        // Calling the accept method
        printLong.accept(100L);
        // Output: 100
    }
}

Example 3: Using andThen to Chain Consumers

The andThen method allows chaining multiple LongConsumer actions. It returns a composite LongConsumer that performs all the operations in sequence.

package org.kodejava.util.function;

import java.util.function.LongConsumer;

public class LongConsumerChaining {
    public static void main(String[] args) {
        LongConsumer printLong = value -> System.out.println("Printing value: " + value);
        LongConsumer doubleValue = value -> System.out.println("Double of value: " + (value * 2));

        LongConsumer combined = printLong.andThen(doubleValue);

        // Calling the combined LongConsumer
        combined.accept(25L);
        // Output:
        // Printing value: 25
        // Double of value: 50
    }
}

Practical Use Case

LongConsumer can be used in scenarios involving streams of long values, such as with the primitive specialization LongStream in the Java Stream API.

package org.kodejava.util.function;

import java.util.function.LongConsumer;
import java.util.stream.LongStream;

public class LongStreamExample {
    public static void main(String[] args) {
        LongConsumer printLong = value -> System.out.print(value + " ");

        // Using LongConsumer with LongStream
        LongStream.range(1, 5).forEach(printLong);
        // Output: 1 2 3 4
    }
}

Key Points:

  1. LongConsumer is a functional interface meant for operations on long values.
  2. It defines one abstract method, accept(long value).
  3. The andThen method is a default method used to chain consumers together.
  4. Useful in functional programming styles and with primitive streams like LongStream.

How do I use the LongBinaryOperator functional interface in Java?

The LongBinaryOperator is a functional interface in Java that is part of the java.util.function package, introduced in Java 8. It represents an operation upon two long values that produces a single long result. This can be thought of as a primitive specialization of the BinaryOperator interface for long types.

Key Features of LongBinaryOperator:

  • It’s a functional interface, so it can be used with a lambda expression or method reference.
  • It has a single abstract method, applyAsLong, which takes two long arguments and returns a long.

Functional Method:

long applyAsLong(long left, long right);

The two parameters (left and right) represent the two long values on which the operation will be performed, and the result is also a long.


Usage

Here are a few examples of how to use the LongBinaryOperator:

Example 1: Using a Lambda Expression

We can define a LongBinaryOperator using a lambda expression:

package org.kodejava.util.function;

import java.util.function.LongBinaryOperator;

public class LongBinaryOperatorExample {
    public static void main(String[] args) {
        // Example: sum of two long values
        LongBinaryOperator sumOperator = (a, b) -> a + b;

        long result = sumOperator.applyAsLong(10L, 20L);
        // Output: Result: 30
        System.out.println("Result: " + result);
    }
}

Example 2: Using a Method Reference

If there’s an existing method that matches the signature of applyAsLong(long, long), we can use a method reference instead of a lambda:

package org.kodejava.util.function;

import java.util.function.LongBinaryOperator;

public class LongBinaryOperatorExample2 {
    public static void main(String[] args) {
        // Example: method reference for multiplying two numbers
        LongBinaryOperator multiplyOperator = Math::multiplyExact;

        long result = multiplyOperator.applyAsLong(10L, 20L);
        // Output: Result: 200
        System.out.println("Result: " + result);
    }
}

Example 3: Custom Implementation

We can also implement the interface explicitly, though this is less common since lambdas are more concise:

package org.kodejava.util.function;

import java.util.function.LongBinaryOperator;

public class LongBinaryOperatorExample3 {
    public static void main(String[] args) {
        LongBinaryOperator customOperator = new LongBinaryOperator() {
            @Override
            public long applyAsLong(long left, long right) {
                // Custom logic: return the larger of the two numbers
                return Math.max(left, right);
            }
        };

        long result = customOperator.applyAsLong(15L, 20L);
        // Output: Result: 20
        System.out.println("Result: " + result);
    }
}

Example 4: Composing with Streams

LongBinaryOperator is often used in combination with streams, such as reducing a series of long values into a single value:

package org.kodejava.util.function;

import java.util.stream.LongStream;
import java.util.function.LongBinaryOperator;

public class LongBinaryOperatorExample4 {
    public static void main(String[] args) {
        LongBinaryOperator maxOperator = Math::max;

        long max = LongStream.of(5L, 10L, 15L, 20L)
                .reduce(0L, maxOperator);

        // Output: Max: 20
        System.out.println("Max: " + max);
    }
}

Summary

The LongBinaryOperator is a simple yet powerful functional interface that allows we to work with long values directly, avoiding boxing and unboxing overheads. It’s mainly useful for scenarios involving two long inputs and one long output, such as mathematical or logical operations. Lambdas, method references, and its integration with streams make it highly versatile and efficient.

How do I use the IntUnaryOperator functional interface in Java?

The IntUnaryOperator is a functional interface in Java that resides in the java.util.function package. It represents a function that accepts a single int-valued argument and produces an int-valued result. It is often used when working with Lambda expressions or method references where we need to process integers.

Here’s a detailed explanation of how to use IntUnaryOperator with examples:


1. Signature of IntUnaryOperator

The IntUnaryOperator interface has a single abstract method:

int applyAsInt(int operand);

This method takes an int as input and returns another int as output.


2. Syntax and Lambda Expression

We can use IntUnaryOperator by providing an implementation of the applyAsInt method, typically through a lambda expression or method reference.

// Doubles the input value
IntUnaryOperator operator = (int x) -> x * 2;
// Result is 10
int result = operator.applyAsInt(5); 

3. Static Methods Available

The interface also provides some default or additional static methods to combine or chain operations:

a. compose method

The compose method allows we to first apply another IntUnaryOperator and then apply the current operator.

IntUnaryOperator operator1 = x -> x + 3; // Adds 3
IntUnaryOperator operator2 = x -> x * 2; // Doubles the value

// First apply 'operator1', then 'operator2'
IntUnaryOperator combined = operator2.compose(operator1);

// Result is (5 + 3) * 2 = 16
int result = combined.applyAsInt(5); 

b. andThen method

This method allows we to first apply the current operator and then apply another operator.

IntUnaryOperator operator1 = x -> x + 3; // Adds 3
IntUnaryOperator operator2 = x -> x * 2; // Doubles the value

// First apply 'operator1', then 'operator2'
IntUnaryOperator combined = operator1.andThen(operator2);

// Result is (5 + 3) * 2 = 16
int result = combined.applyAsInt(5); 

c. identity method

The identity method returns an IntUnaryOperator that always returns its input value unchanged.

IntUnaryOperator identityOperator = IntUnaryOperator.identity();
// Result is 10
int result = identityOperator.applyAsInt(10); 

4. Use Cases

  • Mapping values in an array or collection:
package org.kodejava.util.function;

import java.util.Arrays;
import java.util.function.IntUnaryOperator;

public class MappingValueExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};

        IntUnaryOperator doubleOperator = x -> x * 2;

        int[] doubledNumbers = Arrays.stream(numbers)
                .map(doubleOperator)
                .toArray();

        // Output: [2, 4, 6, 8, 10]
        System.out.println(Arrays.toString(doubledNumbers));
    }
}
  • Chaining multiple operations:
package org.kodejava.util.function;

import java.util.function.IntUnaryOperator;

public class ChainOperationExample {
    public static void main(String[] args) {
        int number = 5;

        IntUnaryOperator addFive = x -> x + 5;
        IntUnaryOperator square = x -> x * x;

        IntUnaryOperator combinedOperator = addFive.andThen(square);
        int result = combinedOperator.applyAsInt(number); // (5 + 5)² = 100

        // Output: Result: 100
        System.out.println("Result: " + result);
    }
}

5. Key Benefits

  • Simplifies working with single-argument integer operations.
  • Performs operations without boxing/unboxing overhead, as it uses primitive int instead of Integer.
  • Easily composable with methods like compose and andThen.

This functional interface is useful in various scenarios, especially when we want to perform operations or transformations on primitive int values in a concise manner.

How do I use the IntToLongFunction functional interface in Java?

The IntToLongFunction functional interface in Java is a specialized @FunctionalInterface introduced in Java 8 as part of the java.util.function package. It represents a function that takes a single int-valued argument and produces a long-valued result. This is intended to avoid boxing and unboxing of primitive values, improving performance when we need to work with these data types.

Key Characteristics of IntToLongFunction

  • Functional Method: The single abstract method in this interface is:
long applyAsLong(int value);
  • It takes an int as input and returns a long.
  • Annotation: It is annotated with @FunctionalInterface, meaning it can be used as a target for lambda expressions or method references.

How to Use IntToLongFunction

We can use the IntToLongFunction in several ways, such as with lambda expressions, method references, or by implementing the interface explicitly.

Example 1: Using Lambda Expressions

package org.kodejava.util.function;

import java.util.function.IntToLongFunction;

public class IntToLongFunctionExample {
   public static void main(String[] args) {
      // Example: Convert an int to its square and return long
      IntToLongFunction intToSquareLong = x -> (long) x * x;

      int input = 5;
      long result = intToSquareLong.applyAsLong(input);

      System.out.println("The square of " + input + " is: " + result);
   }
}

Example 2: Using Method References

If we already have a method that matches the applyAsLong signature, we can use a method reference:

package org.kodejava.util.function;

import java.util.function.IntToLongFunction;

public class IntToLongFunctionExample2 {
   public static void main(String[] args) {
      IntToLongFunction intToHexLong = Integer::toUnsignedLong;

      int input = -10;
      long result = intToHexLong.applyAsLong(input);

      System.out.println("The unsigned long value of " + input + " is: " + result);
   }
}

Example 3: Explicit Implementation of IntToLongFunction

We can explicitly implement the functional interface (though this is less common):

package org.kodejava.util.function;

import java.util.function.IntToLongFunction;

public class IntToLongFunctionExample3 {
   public static void main(String[] args) {
      IntToLongFunction intToDoubleLong = new IntToLongFunction() {
         @Override
         public long applyAsLong(int value) {
            return (long) value * 2;
         }
      };

      int input = 15;
      long result = intToDoubleLong.applyAsLong(input);

      System.out.println("Double of " + input + " is: " + result);
   }
}

Real-World Use Cases

Primitive Stream Processing:

IntToLongFunction can be used with IntStream.mapToLong() to process an IntStream and produce a LongStream.

package org.kodejava.util.function;

import java.util.stream.IntStream;

public class IntToLongStreamExample {
   public static void main(String[] args) {
      IntStream.range(1, 5)
              .mapToLong(x -> (long) x * x)
              .forEach(System.out::println); // Output: 1, 4, 9, 16
   }
}

Custom Transformation Logic:

Use it to convert input int data into a long result in scenarios such as file size calculations, timestamp conversions, or memory addresses. This example demonstrates how the IntToLongFunction can be used to implement custom transformation logic like time conversions, ensuring no boxing/unboxing overhead occurs.

package org.kodejava.util.function;

import java.util.function.IntToLongFunction;

public class CustomTransformationExample {
   public static void main(String[] args) {
      // Converts seconds (int) into milliseconds (long)
      IntToLongFunction secondsToMilliseconds = seconds -> (long) seconds * 1000;

      int seconds = 120; // 120 seconds = 2 minutes
      long milliseconds = secondsToMilliseconds.applyAsLong(seconds);

      System.out.println(seconds + " seconds is equal to " + milliseconds + " milliseconds.");
   }
}

Output:

120 seconds is equal to 120000 milliseconds.

Summary

The IntToLongFunction functional interface is highly useful when we need to work with int and long primitives while avoiding the overhead of boxing and unboxing. We can use it with lambda expressions, method references, or explicitly implement it based on the needs of our application.