These interfaces:
- Take two arguments: one of a generic object type
T
and one primitive (double
,int
, orlong
) - Return nothing (
void
) - Are used when you want to perform an action (consume values), without boxing the primitive
✅ 1. ObjDoubleConsumer<T>
@FunctionalInterface
public interface ObjDoubleConsumer<T> {
void accept(T t, double value);
}
🧠 Example:
ObjDoubleConsumer<String> printPrice = (product, price) ->
System.out.println(product + " costs $" + price);
printPrice.accept("Coffee", 4.99); // Output: Coffee costs $4.99
✅ 2. ObjIntConsumer<T>
@FunctionalInterface
public interface ObjIntConsumer<T> {
void accept(T t, int value);
}
🧠 Example:
ObjIntConsumer<String> printQuantity = (item, quantity) ->
System.out.println(quantity + " x " + item);
printQuantity.accept("Apples", 5); // Output: 5 x Apples
✅ 3. ObjLongConsumer<T>
@FunctionalInterface
public interface ObjLongConsumer<T> {
void accept(T t, long value);
}
🧠 Example:
ObjLongConsumer<String> logTimestamp = (event, timestamp) ->
System.out.println("[" + timestamp + "] Event: " + event);
logTimestamp.accept("UserLogin", System.currentTimeMillis());
🔧 Why Use These?
Feature | Value |
---|---|
✅ Avoid boxing | No Integer , Double , or Long objects needed |
✅ Stream-friendly | Often used in custom collectors, batch processors, etc. |
✅ Descriptive | Makes it clear you’re working with an object and a primitive |
🔄 Summary Table
Interface | Parameters | Return | Description |
---|---|---|---|
ObjDoubleConsumer<T> | T , double | void | Consumes an object and a double |
ObjIntConsumer<T> | T , int | void | Consumes an object and an int |
ObjLongConsumer<T> | T , long | void | Consumes an object and a long |
✅ Real Use Case?
Suppose you’re processing a product and want to log how many units were sold:
ObjIntConsumer<Product> logSale = (product, qty) ->
System.out.println("Sold " + qty + " units of " + product.getName());