欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

How to use Java functional Consumer interface example

程序员文章站 2022-06-07 14:30:23
...

Quite often a Java Stream or other component needs an object passed to it in order to perform some type of calculation or process, but when the process is complete, nothing gets returned from the method. This is where Java’s functional Consumer interface comes in handy.

通常,Java Stream或其它组件需要将传递给它的对象以执行某种类型的计算和过程,但是当过程完成时,该方法不会返回任何内容。这是Java的"消费者"函数式接口方便使用的地方

According to the JavaDoc, the Consumer interface accepts any type of object as input. The java.util.function.Consumer class has one non-default method named accept which takes a single object as its argument and has a void return type.

根据JavaDoc, 消费者接口可以接受任何类型的对象作为输入。java.util.functional.Consumer类具有一个名为accept的非默认方法

java.util.function.Consumer<T>
Consumer function type Parameters:
T - object type to be passed to the Consumer accept method
    
Consumer function methods:
void accept(T t)  This method operates on a single object passed in as an argument.
default Consumer<T> andThen(Consumer after)  Returns a functional Consumer interface that can be daisy chained in sequence.
    

The Consumer's non-default accept method takes a single argument and does not return a result.

Functional programming with a Java Consumer

Sometimes programmers new to lambdas and streams get intimidated by the components defined in the java.util.function package, so I always like to remind developers that all of the interfaced defined in this package follow all of the standard, pre Java 8 rules for implementing interfaces. As such, you can incorporate the functional Consumer interface into your code simply by creating a class that implements java.util.function.Consumer, or by coding an inner class.

刚接触lambda和流的程序员会被java.util.function包中定义的组件吓倒,因此总是想提醒开发人员,此包中定义的所有接口都遵循Java 8之前的所有标准实现规则接口。这样,您可以简单地通过创建实现java.util.function.Consumer的类或对内部类进行编码,将函数式的Consumer接口纳入代码中。

Implement a Consumer with a Java class

Here is the Java Consumer function implemented using a Java class instead of a lambda expression:

这是使用Java类而不是lambda表达式实现的Java Consumer函数:

class SimpleConsumerExample implements Consumer<Long> {
    
    public void accept(Long t) {
    
        System.out.println(t * t);
    }
}

Inside of a main method or any other piece of Java code, the SimpleConsumerExample class can be instatiated according to traditional Java syntax rules:

在main方法或任何其它Java代码段中,可以根据传统的Java与语法规则将SimpleConsumerExample类实例化

/* Java Consumer example using a class */
SimpleConsumerExample sce = new SimpleConsumerExample();

sce.accept(new Long(2));

Similarly, an inner class can also be used:

/* Functional Consumer example using inner class */
Consumer<Long> innerConsumer = new Consumer<Long>() {
    @Override
  	public void accept(Long t) {
        
    	System.out.println(t*t);
  	}
};

innerConsumer.accept(new Long(4));

Lambda and Consumer interface example

As you can see, there is nothing special about the interfaces defined in the java.util.function package. They are regular Java interfaces that comply with all of the traditional rules of syntax. However, they also work with lambda expressions, which is where functional interfaces really shine. Here is the functional Consumer interface example implemented using a somewhat verbose lambda expression:

如您所见,java.util.function包中定义的接口没有什么特别的。它们是符合所有传统语法规则的常规Java接口。但是,它们也可以与lambda表达式一起使用,而lambda表达式正是函数式接口的真正亮口真正的亮点。这是使用有些冗长的lambda表达式实现的功能性Consumer接口示例:

Consumer<Long> lambdaConsumer = (Long t) -> System.out.println(t * t);

lambdaConsumer.accept(new Long(5));

I like to use a verbose lambda syntax when demonstrating how they work, but one of the reasons for using lambda expressions is to make Java less verbose. So the lambda expression above can be written in a much more concise manner:

在演示它们如何工作时,我喜欢使用冗长的lambda语法,但是使用lambda表达式的原因之一是使Java不再那么冗长。因此,上面的lambda表达式可以用更简洁的方式编写:

Consumer<Long> conciseLambda = t -> System.out.println(t * t);

conciseLambda.accept(new Long(10));

Sample Consumer interface use cases

The functional Consumer interface is used extensively across the Java API, with a number of classes in the java.util.function package, such as ObjIntConsumer, BIConsumer and IntConsumer providing extended support to the basic interface.

函数式Consumer接口在Java API中得到了广泛使用,并在java.util.function包中提供了许多类,例如ObjIntConsumer,BIConsumer和IntConsumer,它们为基本接口提供了扩展的支持。

Furthermore, a variety of methods in the Java Stream API take the functional Consumer interface as an argument, inclusing methods such as collect, forEach and peek.

此外,Java Stream API中的各种方法都将函数式Consumer接口作为参数,包括collect,forEach和peek等方法。

There are only a few key intefaces you need to master in order to become a competent functional programmer. If you understand the concepts laid out in this functional Consumer interface example, you’re well on your way to mastering the update Java APIs.

成为熟练的功能程序员,您只需要掌握几个关键的接口即可。如果您了解此实用的使用者接口示例中列出的概念,那么您就可以很好地掌握更新Java API。

Consumer tutorial code

Here is the code used in this tutorial on how to use the Consumer.

package com.zetcode.Consumer;

import java.util.function.Consumer;

public class JavaConsumerExample {

    public static void main(String[] args) {

        // Java Consumer example using a class
        SimpleConsumerExample sce = new SimpleConsumerExample();
        sce.accept(new Long(2));

        // Functional Consumer example using inner class
        Consumer<Long> innerConsumer = new Consumer<Long>() {
            @Override
            public void accept(Long aLong) {
                System.out.println(aLong * aLong);
            }
        };
        innerConsumer.accept(new Long(4));

        // Consumer example with lambda expression
        Consumer<Long> lambdaConsumer = (Long t) -> System.out.println(t * t);
        lambdaConsumer.accept(new Long(5));

        // Concise lambda with the Consumer function
        Consumer<Long> conciseLambda = t -> System.out.println(t * t);
        conciseLambda.accept(new Long(6));
    }
}

class SimpleConsumerExample implements Consumer<Long> {

    public void accept(Long t) {

        System.out.println(t * t);
    }
}

Output

4
16
25
36

Java Lambda - Consumer example

Consumer interface represents an operation that accepts a single input argument and returns no result.

Method

  1. Consumer accept
  2. Consumer andThen

Consumer accept performs operation on the given argument.

Syntax

accept has the following syntax.

void accept(T t)

Example 01

The following example shows how to use accept.

package com.zetcode.Consumer;

import java.util.function.Consumer;

public class ConsumerExample01 {

    public static void main(String[] args) {
        Consumer<String> str = x -> System.out.println(x.toLowerCase());
        str.accept("Java Consumer Example");
    }
}

Output

java consumer example

Example 02

The following code shows how to pass Consumer to forEach method

package com.zetcode.Consumer;

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

public class ConsumerExample02 {

    public static void main(String[] args) {

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        numbers.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                
                System.out.println(integer);
            }
        });
    }
}

Output

1
2
3
4
5
6
7
8
9
10

Java Lambda - Consumer andThen example

Consumer andThen returns a composed Consumer that performs, in sequence, for the current operation followed by the after operation.

该消费者依次执行当前操作和随后的操作

Syntax

andThen has the following syntax.

default Consumer<T> andThen(Consumer<? super T> after)

Example 01

The following example shows how to use andThen.

package com.zetcode.Consumer;

import java.util.function.Consumer;

public class AndThenExample01 {

    public static void main(String[] args) {

        Consumer<String> str = x -> System.out.println(x.toLowerCase());
        str.andThen(str).accept("JAVA CONSUMER EXAMPLE");
    }
}

The code above generates the following result.

Output

java consumer example
java consumer example

Example 02

The following code shows how to chain Consumer to chain actions.

package com.zetcode.Consumer;

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

public class AndThenExample02 {

    public static void main(String[] args) {


        List<Student> students = Arrays.asList(
                new Student(1, 3, "John"),
                new Student(2, 4, "Jane"),
                new Student(3, 3, "Jack"));

        Consumer<Student> raiser = e -> {
            e.gpa = e.gpa * 1.1;
        };

        raiseStudents(students, System.out::println);
        raiseStudents(students, raiser.andThen(System.out::println));

    }

    private static void raiseStudents(List<Student> employees, Consumer<Student> fx) {
        for (Student e : employees) {
            fx.accept(e);
        }
    }
}

class Student {
    public int id;
    public double gpa;
    public String name;

    public Student(int id, double gpa, String name) {
        this.id = id;
        this.gpa = gpa;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", gpa=" + gpa +
                ", name='" + name + '\'' +
                '}';
    }
}

The code above generates the following result.

Student{id=1, gpa=3.0, name='John'}
Student{id=2, gpa=4.0, name='Jane'}
Student{id=3, gpa=3.0, name='Jack'}
Student{id=1, gpa=3.3000000000000003, name='John'}
Student{id=2, gpa=4.4, name='Jane'}
Student{id=3, gpa=3.3000000000000003, name='Jack'}

The following code shows how to create consumer with block statement.

package com.zetcode.Consumer;

import java.util.function.Consumer;

public class ConsumerSample {

    public static void main(String[] args) {
        int x = 99;

        Consumer<Integer> myConsumer = y -> {
            System.out.println("x = " + x);
            System.out.println("y = " + y);
        };
        myConsumer.accept(x);
    }
}

The code above generates the following result.

x = 99
y = 99

The following code shows how to pass Consumer as parameter.

package com.zetcode.Consumer;


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

public class ConsumerSample03 {

    public static void main(String[] args) {
        List<Student> students = Arrays.asList(
                new Student("John", 3),
                new Student("Mark", 4)
        );

        acceptAplEmployee(students, e -> System.out.println(e.name));
        acceptAplEmployee(students, e -> {
            e.gpa *= 1.5;
        });
        acceptAplEmployee(students, e-> System.out.println(e.name + ": " + e.gpa));
    }

    public static void acceptAplEmployee(List<Student> student, Consumer<Student> printer) {
        for (Student e : student) {
            printer.accept(e);
        }
    }
}

class Student {
    public String name;
    public double gpa;

    public Student(String name, double gpa) {
        this.name = name;
        this.gpa = gpa;
    }
}

The code above generates the following result.

John
Mark
John: 4.5
Mark: 6.0

Java 8 | Consumer Interface in Java with Examples

The Consumer Interface is a part of the java.util.function package which has been introduced since Java 8, to implement functional programming in Java. It represents a function which takes in one argument and produces a result. However these kind of functions don’t return any value.

消费者接口是java.util.function包的一部分,该包是从Java 8开始引入的,用于用Java实现函数式编程。它代表接受一个参数并产生结果的函数。但是,这类函数不会返回任何值。

Hence this functional interface which takes in one generic namely:

  • T: denotes the type of the input argument to the operation

The lambda expression assigned to an object of Consumer type is used to define its accept() which eventually applies the given operation on its argument. Consumers are useful when it not needed to return any value as they are expected to operate via side-effects.

分配给Consumer类型的对象的lambda表达式用于定义其accept(),最终将给定操作应用于其参数。当不需要返回任何值(因为期望通过副作用进行操作)时,消费者将非常有用。

Functions in Consumer Interface

The Consumer interface consists of the following two functions:

1. accept()

This method accepts one value and performs the operation on the given argument

Syntax:

void accept(T t)

Parameters: This method takes in one parameter:

  • t– the input argument

Returns: This method does not return any value.

Below is the code to illustrate accept() method:

package com.zetcode.Consumer;

// Java Program to demonstrate
// Consumer's accept() method

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

public class ConsumerAccept {

    public static void main(String args[]) {
        // Consumer to display a number
        Consumer<Integer> display = a -> System.out.println(a);

        // Implement display using accept()
        display.accept(10);

        // Consumer to multiply 2 to every integer of a list
        Consumer<List<Integer>> modify = list ->
        {
            for (int i = 0; i < list.size(); i++)
                list.set(i, 2 * list.get(i));
        };

        // Consumer to display a list of numbers
        Consumer<List<Integer>>
                dispList = list -> list.stream().forEach(a -> System.out.print(a + " "));

        List<Integer> list = new ArrayList<Integer>();
        list.add(2);
        list.add(1);
        list.add(3);

        // Implement modify using accept()
        modify.accept(list);

        // Implement dispList using accept()
        dispList.accept(list);
    }
}
10
4 2 6 
2. andThen()

It returns a composed Comsumer wherein the parameterized Consumer will be executed after the first one. If evaluation of either function throws an error, it is relayed to the caller of the composed operation.

它返回一个合成的消费者,其中参数化的消费者将在第一个消费者之执行。

Note: The function being passed as the argument should be of type Consumer.

Syntax:

default Consumer <T> 
        andThen(Consumer<? super T> after)

Parameters: This method accepts a parameter after which is the Consumer to be applied after the current one.

Return Value: This method returns a composed Consumer that first applies the current Consumer first and then the after operation.

Exception: This method throws NullPointerException if the after operation is null.

Below is the code to illustrate andThen() method:

package com.zetcode.Consumer;

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

public class AndThenTutorial01 {

    public static void main(String[] args) {

        // Consumer to multiply 2 to every integer of a list
        Consumer<List<Integer>> modify = list -> {
            for (int i = 0; i < list.size(); i++) {
                list.set(i, 2 * list.get(i));
            }
        };

        // Consumer to display a list of integers
        Consumer<List<Integer>> dispList = list -> list.stream().forEach(a -> System.out.print(a + " "));

        List<Integer> list = new ArrayList<>();
        list.add(2);
        list.add(1);
        list.add(3);

        // using addThen
        modify.andThen(dispList).accept(list);
    }
}

Output

4 2 6

Program 2: To demonstrate when NullPointerException is returned.

package com.zetcode.Consumer;

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

public class AndThenTutorials02 {

    public static void main(String[] args) {

        // Consumer to multiply 2 to every integer of a list
        Consumer<List<Integer>> modify = list -> {
            for (int i = 0; i < list.size(); i++) {
                list.set(i, 2 * list.get(i));
            }
        };

        // Consumer to display a list of integers
        Consumer<List<Integer>> dispList = list -> list.stream().forEach(a -> System.out.print(a + " "));
        List<Integer> list = new ArrayList<Integer>();
        list.add(2);
        list.add(1);
        list.add(3);
        try {
            // using andThen()
            modify.andThen(null).accept(list);
        } catch (Exception e) {
            System.out.println("Exception : " + e);
        }
    }
}

Output

Exception : java.lang.NullPointerException

Program 3: To demonstrate how an Exception in the after function is returned and handled.

// Java Program to demonstrate 
// Consumer's andThen() method 

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

public class Main { 
    
	public static void main(String args[]) { 

		// Consumer to multiply 2 to every integer of a list 
		Consumer<List<Integer> > modify = list -> 
        { 
			for (int i = 0; i <= list.size(); i++) 
				list.set(i, 2 * list.get(i)); 
		}; 

		// Consumer to display a list of integers 
		Consumer<List<Integer> > 
			dispList = list -> list.stream().forEach(a -> System.out.print(a + " ")); 
		System.out.println(); 

		List<Integer> list = new ArrayList<Integer>(); 
		list.add(2); 
		list.add(1); 
		list.add(3); 

		// using addThen() 
		try { 
			dispList.andThen(modify).accept(list); 
		} 
		catch (Exception e) { 
			System.out.println("Exception: " + e); 
		} 
	} 
} 

Output

2 1 3 Exception: java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
相关标签: Java