ZetCode

Java ObjLongConsumer 接口

最后修改时间:2025 年 4 月 16 日

java.util.function.ObjLongConsumer 接口代表一个接受对象和 long 类型参数的操作。它是一个函数式接口,只有一个抽象方法 accept。该接口专门用于 long 原始类型,以避免装箱开销。

ObjLongConsumer 是 Java 8 中添加的 Java 函数式编程实用程序的一部分。它允许行为参数化,用于需要对象和 long 参数的操作。该接口常用于流处理和集合操作。

ObjLongConsumer 接口概述

ObjLongConsumer 接口包含一个抽象方法,该方法对给定的参数执行操作。与常规的消费者不同,它接受两个参数 - 一个对象和一个 long 原始类型。

@FunctionalInterface
public interface ObjLongConsumer<T> {
    void accept(T t, long value);
}

上面的代码显示了 ObjLongConsumer 接口的结构。它对对象参数使用泛型,而第二个参数始终是 long 类型。该接口用 @FunctionalInterface 标注。

ObjLongConsumer 的基本用法

使用 ObjLongConsumer 的最简单方法是使用 lambda 表达式。我们在 accept 方法中定义如何处理对象和 long 参数。此示例展示了一个记录产品更新的消费者。

Main.java
package com.zetcode;

import java.util.function.ObjLongConsumer;

public class Main {

    public static void main(String[] args) {

        // Define a consumer for product updates
        ObjLongConsumer<String> productUpdater = (name, newStock) -> {
            System.out.printf("Updating product '%s' with new stock: %d%n", 
                name, newStock);
        };
        
        // Use the consumer
        productUpdater.accept("Laptop", 150L);
        productUpdater.accept("Smartphone", 300L);
    }
}

此示例演示了 ObjLongConsumer 的基本用法。productUpdater 接受产品名称(String)和新的库存值(long)。它打印每件产品的更新消息。消费者执行一个动作,不返回任何结果。

ObjLongConsumer 与集合

ObjLongConsumer 可用于处理集合中的元素。此示例演示了如何更新地图中产品的库存数量。

Main.java
package com.zetcode;

import java.util.HashMap;
import java.util.Map;
import java.util.function.ObjLongConsumer;

public class Main {

    public static void main(String[] args) {

        Map<String, Long> inventory = new HashMap<>();
        inventory.put("Keyboard", 50L);
        inventory.put("Mouse", 75L);
        inventory.put("Monitor", 30L);
        
        // Consumer to update inventory
        ObjLongConsumer<String> inventoryUpdater = (product, quantity) -> {
            inventory.merge(product, quantity, Long::sum);
        };
        
        // Apply updates
        inventoryUpdater.accept("Keyboard", 20L);
        inventoryUpdater.accept("Monitor", 15L);
        inventoryUpdater.accept("Headphones", 40L); // New product
        
        System.out.println("Updated inventory: " + inventory);
    }
}

此示例展示了 ObjLongConsumer 与集合。inventoryUpdater 将数量添加到现有产品或创建新条目。Map.merge 方法处理这两种情况。这种模式对于批量更新很有用。

ObjLongConsumer 在流处理中

ObjLongConsumer 可用于需要同时处理对象和 long 值的流操作。此示例计算订单项目的总价格。

Main.java
package com.zetcode;

import java.util.List;
import java.util.function.ObjLongConsumer;

public class Main {

    public static void main(String[] args) {

        record OrderItem(String name, double price, int quantity) {}
        
        List<OrderItem> orderItems = List.of(
            new OrderItem("Shirt", 29.99, 2),
            new OrderItem("Pants", 49.99, 1),
            new OrderItem("Shoes", 89.99, 1)
        );
        
        // Consumer to calculate total price
        ObjLongConsumer<OrderItem> priceCalculator = (item, total) -> {
            double itemTotal = item.price() * item.quantity();
            System.out.printf("%s: %.2f x %d = %.2f (Running total: %d)%n",
                item.name(), item.price(), item.quantity(), 
                itemTotal, total + (long) itemTotal);
        };
        
        // Process with running total
        long runningTotal = 0;
        for (OrderItem item : orderItems) {
            priceCalculator.accept(item, runningTotal);
            runningTotal += (long) (item.price() * item.quantity());
        }
    }
}

此示例演示了 ObjLongConsumer 在类似流的处理中。priceCalculator 显示每个项目的总额和运行总和。虽然没有直接使用 Stream API,但它展示了用于顺序处理的消费者模式。

ObjLongConsumer 与原始数组

ObjLongConsumer 适用于原始数组,我们需要使用附加上下文处理元素。此示例使用位置信息处理温度读数。

Main.java
package com.zetcode;

import java.util.function.ObjLongConsumer;

public class Main {

    public static void main(String[] args) {

        long[] temperatures = {22L, 24L, 19L, 21L, 25L};
        String location = "New York";
        
        // Consumer to process temperature readings
        ObjLongConsumer<String> tempProcessor = (loc, temp) -> {
            String condition = temp > 23 ? "Warm" : 
                             temp < 20 ? "Cool" : "Mild";
            System.out.printf("%s: %d°C (%s)%n", loc, temp, condition);
        };
        
        // Process all temperatures
        for (long temp : temperatures) {
            tempProcessor.accept(location, temp);
        }
    }
}

此示例展示了 ObjLongConsumer 与原始数组。tempProcessor 接受位置上下文和温度值。它对每个读数进行分类并打印格式化的消息。消费者处理对象和原始类型。

ObjLongConsumer 用于对象状态修改

ObjLongConsumer 可以根据 long 参数修改对象状态。此示例使用交易金额更新银行帐户余额。

Main.java
package com.zetcode;

import java.util.function.ObjLongConsumer;

public class Main {

    static class BankAccount {
        private String owner;
        private long balance;
        
        public BankAccount(String owner, long balance) {
            this.owner = owner;
            this.balance = balance;
        }
        
        public void processTransaction(ObjLongConsumer<BankAccount> operation, 
                                      long amount) {
            operation.accept(this, amount);
        }
        
        @Override
        public String toString() {
            return owner + "'s account: $" + balance;
        }
    }
    
    public static void main(String[] args) {

        BankAccount account = new BankAccount("John", 1000L);
        
        // Define deposit operation
        ObjLongConsumer<BankAccount> deposit = (acc, amount) -> {
            acc.balance += amount;
            System.out.println("Deposited: $" + amount);
        };
        
        // Define withdrawal operation
        ObjLongConsumer<BankAccount> withdraw = (acc, amount) -> {
            if (acc.balance >= amount) {
                acc.balance -= amount;
                System.out.println("Withdrawn: $" + amount);
            } else {
                System.out.println("Insufficient funds for withdrawal: $" + amount);
            }
        };
        
        // Process transactions
        account.processTransaction(deposit, 500L);
        System.out.println(account);
        
        account.processTransaction(withdraw, 200L);
        System.out.println(account);
        
        account.processTransaction(withdraw, 2000L);
        System.out.println(account);
    }
}

此示例演示了使用 ObjLongConsumer 的状态修改。BankAccount 类使用消费者进行存款和取款。每个操作都接收帐户对象和交易金额。这封装了行为。

ObjLongConsumer 在方法参数中

ObjLongConsumer 可以作为方法参数传递,以实现灵活的行为。此示例显示了一个接受消费者的通用数据处理器。

Main.java
package com.zetcode;

import java.util.function.ObjLongConsumer;

public class Main {

    static void processData(String[] items, long[] values, 
                          ObjLongConsumer<String> processor) {
        if (items.length != values.length) {
            throw new IllegalArgumentException("Arrays must have equal length");
        }
        
        for (int i = 0; i < items.length; i++) {
            processor.accept(items[i], values[i]);
        }
    }
    
    public static void main(String[] args) {

        String[] products = {"Tablet", "Laptop", "Phone"};
        long[] sales = {1500L, 2300L, 3100L};
        
        // Consumer to print product sales
        ObjLongConsumer<String> salesReporter = (product, count) -> {
            System.out.printf("%-10s: %5d units%n", product, count);
        };
        
        // Consumer to calculate revenue (assuming $500 per unit)
        ObjLongConsumer<String> revenueCalculator = (product, count) -> {
            long revenue = count * 500;
            System.out.printf("%-10s: $%,d%n", product, revenue);
        };
        
        System.out.println("Sales Report:");
        processData(products, sales, salesReporter);
        
        System.out.println("\nRevenue Estimate:");
        processData(products, sales, revenueCalculator);
    }
}

此示例展示了 ObjLongConsumer 作为方法参数。processData 方法接受任何消费者来处理成对的 String 和 long 值。不同的消费者提供了不同的处理方式,而无需修改核心方法。

将 ObjLongConsumer 与其他函数式接口结合使用

ObjLongConsumer 可以与其他函数式接口结合使用,以进行更复杂的操作。此示例展示了在消费之前进行过滤。

Main.java
package com.zetcode;

import java.util.function.ObjLongConsumer;
import java.util.function.LongPredicate;

public class Main {

    public static void main(String[] args) {

        record SensorReading(String sensorId, long value) {}
        
        SensorReading[] readings = {
            new SensorReading("TEMP-1", 22L),
            new SensorReading("TEMP-2", 45L),  // Invalid
            new SensorReading("TEMP-3", 18L),
            new SensorReading("TEMP-4", 50L)   // Invalid
        };
        
        // Predicate to validate readings
        LongPredicate isValid = value -> value >= 20L && value <= 30L;
        
        // Consumer to process valid readings
        ObjLongConsumer<String> readingProcessor = (id, value) -> {
            System.out.printf("Processing valid reading - %s: %d%n", id, value);
            // Additional processing logic here
        };
        
        // Process readings with filter
        for (SensorReading reading : readings) {
            if (isValid.test(reading.value())) {
                readingProcessor.accept(reading.sensorId(), reading.value());
            } else {
                System.out.printf("Skipping invalid reading - %s: %d%n", 
                    reading.sensorId(), reading.value());
            }
        }
    }
}

此示例将 ObjLongConsumer 与 LongPredicate 结合使用。isValid 谓词在处理之前过滤读数。readingProcessor 仅接收有效值。这种模式实现了关注点的清晰分离。

来源

Java ObjLongConsumer 接口文档

在本文中,我们介绍了 Java ObjLongConsumer 接口的基本方法和特性。了解这些概念对于有效处理需要对象和 long 原始类型参数的操作至关重要。

作者

我的名字是 Jan Bodnar,是一位经验丰富的程序员。我在该领域拥有多年的经验。我从 2007 年开始撰写编程文章,至今已撰写了 1400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程