ZetCode

Java Consumer

上次修改时间:2024 年 2 月 24 日

在本文中,我们将展示如何在 Java 中使用 Consumer 函数式接口。

Consumer

Consumer 是一个 Java 函数式接口,它表示接受单个输入参数且不返回任何结果的操作。 与大多数其他函数式接口不同,Consumer 预计通过副作用进行操作。

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

Consumer 的函数方法是 accept(Object)。 它可以作为 lambda 表达式或方法引用的赋值目标。

Java Consumer 示例

以下示例创建一个简单的 consumer。

Main.java
import java.util.function.Consumer;

void main() {

    Consumer<String> showThreeTimes = value -> {

        System.out.println(value);
        System.out.println(value);
        System.out.println(value);
    };

    showThreeTimes.accept("blue sky");
    showThreeTimes.accept("old falcon");
}

showThreeTimes consumer 将输入打印三次。

$ java Main.java
blue sky
blue sky
blue sky
old falcon
old falcon
old falcon

IntConsumer

IntConsumer 表示接受单个 int 值参数且不返回任何结果的操作。 这是 Consumer 对于 int 的原始类型特化。

Main.java
import java.util.function.Consumer;
import java.util.function.IntConsumer;

void main() {

    Consumer<Integer> printMultiplyBy100 = (val) -> System.out.println(val * 100);

    printMultiplyBy100.accept(3);
    printMultiplyBy100.accept(4);
    printMultiplyBy100.accept(5);

    IntConsumer printMultiplyBy500 = a -> System.out.println(a * 50);
    printMultiplyBy500.accept(1);
    printMultiplyBy500.accept(2);
    printMultiplyBy500.accept(3);
}

在该示例中,consumer 将输入值相乘。

$ java Main.java
300
400
500
50
100
150

Consumer forEach

forEach 方法接受一个 Consumer 作为参数。 可以使用 lambda 表达式或方法引用简化 consumer。

Main.java
import java.util.List;
import java.util.function.Consumer;

void main() {

    var words = List.of("falcon", "wood", "rock", "forest",
            "river", "water");

    words.forEach(new Consumer<String>() {
        @Override
        public void accept(String s) {

            System.out.println(s);
        }
    });
}

在该示例中,我们使用 forEach 遍历列表的元素。 consumer 只是简单地打印每个元素。

$ java Main.java
falcon
wood
rock
forest
river
water

Consumer andThen

andThen 方法返回一个组合的 Consumer,它按顺序执行此操作,然后执行下一个操作。

Main.java
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

void main() {

    var vals = new ArrayList<Integer>();
    vals.add(2);
    vals.add(4);
    vals.add(6);
    vals.add(8);

    Consumer<List<Integer>> addTwo = list -> {

        for (int i = 0; i < list.size(); i++) {

            list.set(i, 2 + list.get(i));
        }
    };

    Consumer<List<Integer>> showList = list -> 
        list.forEach(System.out::println);

    addTwo.andThen(showList).accept(vals);
}

在该示例中,我们将值 2 添加到列表中的每个元素,然后打印所有元素。

$ java Main.java
4
6
8
10

在以下示例中,我们处理一个产品列表。

Main.java
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

final RoundingMode ROUNDING_MODE = RoundingMode.HALF_EVEN;
final int DECIMALS = 2;

void main() {

    List<Product> products = new ArrayList<>();
    products.add(new Product("A", new BigDecimal("2.54")));
    products.add(new Product("B", new BigDecimal("3.89")));
    products.add(new Product("C", new BigDecimal("5.99")));
    products.add(new Product("D", new BigDecimal("9.99")));

    Consumer<Product> incPrice = p -> {
        p.setPrice(rounded(p.getPrice().multiply(new BigDecimal("1.1"))));
    };

    process(products, incPrice.andThen(System.out::println));
}

BigDecimal rounded(BigDecimal number){
    return number.setScale(DECIMALS, ROUNDING_MODE);
}

void process(List<Product> data, Consumer<Product> cons) {

    for (var e : data) {

        cons.accept(e);
    }
}

class Product {

    private String name;
    private BigDecimal price;

    public Product(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    @Override
    public String toString() {

        var sb = new StringBuilder("Product{");
        sb.append("name='").append(name).append('\'');
        sb.append(", price=").append(price);
        sb.append('}');
        return sb.toString();
    }
}

此示例将产品的价格提高 10%。

Consumer<Product> incPrice = p -> {
    p.setPrice(rounded(p.getPrice().multiply(new BigDecimal("1.1"))));
};

consumer 将产品价格提高 10% 并对该值进行四舍五入。

process(products, incPrice.andThen(System.out::println));

我们提高价格,然后打印修改后的产品。

void process(List<Product> data, Consumer<Product> cons) {

    for (var e : data) {

        cons.accept(e);
    }
}

consumer 应用于列表中的每个产品。

$ java Main.java
Product{name='A', price=2.79}
Product{name='B', price=4.28}
Product{name='C', price=6.59}
Product{name='D', price=10.99}

带有自定义 forEach 的 Consumer

以下示例创建一个自定义的、通用的 forEach 方法。

Main.java
import java.util.List;
import java.util.function.Consumer;

void main() {

    var data = List.of(1, 2, 3, 4, 5, 6, 7);

    // Consumer<Integer> consumer = (Integer x) -> System.out.println(x);
    Consumer<Integer> consumer = System.out::println;
    forEach(data, consumer);

    System.out.println("--------------------------");

    forEach(data, System.out::println);
}

<T> void forEach(List<T> data, Consumer<T> consumer) {

    for (T t : data) {

        consumer.accept(t);
    }
}

我们有一个整数列表。 我们使用自定义的 forEach 方法打印列表的所有元素。

$ java Main.java
1
2
3
4
5
6
7
--------------------------
1
2
3
4
5
6
7

来源

Java Consumer - 语言参考

在本文中,我们使用了 Java Consumer 接口。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有Java教程