什么是函数式接口?
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。也叫做SAM ,即Single Abstract Method interfaces。
函数接口用在什么地方?
函数式接口可以被隐式转换为lambda表达式。
也可以用在方法引用上。
JDK 1.8之前已有的函数式接口:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
JDK 1.8 新增加的函数接口:
- java.util.function
java.util.function 它包含了很多类,用来支持 Java的 函数式编程,该包中的函数式接口有:
序号 | 接口 & 描述 |
---|---|
1 | BiConsumer<T,U> 代表了一个接受两个输入参数的操作,并且不返回任何结果 |
2 | BiFunction<T,U,R> 代表了一个接受两个输入参数的方法,并且返回一个结果 |
3 | BinaryOperator<T> 代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果 |
4 | BiPredicate<T,U> 代表了一个两个参数的boolean值方法 |
5 | BooleanSupplier 代表了boolean值结果的提供方 |
6 | Consumer<T> 代表了接受一个输入参数并且无返回的操作 |
7 | DoubleBinaryOperator 代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。 |
8 | DoubleConsumer 代表一个接受double值参数的操作,并且不返回结果。 |
9 | DoubleFunction<R> 代表接受一个double值参数的方法,并且返回结果 |
10 | DoublePredicate 代表一个拥有double值参数的boolean值方法 |
11 | DoubleSupplier 代表一个double值结构的提供方 |
12 | DoubleToIntFunction 接受一个double类型输入,返回一个int类型结果。 |
13 | DoubleToLongFunction 接受一个double类型输入,返回一个long类型结果 |
14 | DoubleUnaryOperator 接受一个参数同为类型double,返回值类型也为double 。 |
15 | Function<T,R> 接受一个输入参数,返回一个结果。 |
16 | IntBinaryOperator 接受两个参数同为类型int,返回值类型也为int 。 |
17 | IntConsumer 接受一个int类型的输入参数,无返回值 。 |
18 | IntFunction<R> 接受一个int类型输入参数,返回一个结果 。 |
19 | IntPredicate :接受一个int输入参数,返回一个布尔值的结果。 |
20 | IntSupplier 无参数,返回一个int类型结果。 |
21 | IntToDoubleFunction 接受一个int类型输入,返回一个double类型结果 。 |
22 | IntToLongFunction 接受一个int类型输入,返回一个long类型结果。 |
23 | IntUnaryOperator 接受一个参数同为类型int,返回值类型也为int 。 |
24 | LongBinaryOperator 接受两个参数同为类型long,返回值类型也为long。 |
25 | LongConsumer 接受一个long类型的输入参数,无返回值。 |
26 | LongFunction<R> 接受一个long类型输入参数,返回一个结果。 |
27 | LongPredicate R接受一个long输入参数,返回一个布尔值类型结果。 |
28 | LongSupplier 无参数,返回一个结果long类型的值。 |
29 | LongToDoubleFunction 接受一个long类型输入,返回一个double类型结果。 |
30 | LongToIntFunction 接受一个long类型输入,返回一个int类型结果。 |
31 | LongUnaryOperator 接受一个参数同为类型long,返回值类型也为long。 |
32 | ObjDoubleConsumer<T> 接受一个object类型和一个double类型的输入参数,无返回值。 |
33 | ObjIntConsumer<T> 接受一个object类型和一个int类型的输入参数,无返回值。 |
34 | ObjLongConsumer<T> 接受一个object类型和一个long类型的输入参数,无返回值。 |
35 | Predicate<T> 接受一个输入参数,返回一个布尔值结果。 |
36 | Supplier<T> 无参数,返回一个结果。 |
37 | ToDoubleBiFunction<T,U> 接受两个输入参数,返回一个double类型结果 |
38 | ToDoubleFunction<T> 接受一个输入参数,返回一个double类型结果 |
39 | ToIntBiFunction<T,U> 接受两个输入参数,返回一个int类型结果。 |
40 | ToIntFunction<T> 接受一个输入参数,返回一个int类型结果。 |
41 | ToLongBiFunction<T,U> 接受两个输入参数,返回一个long类型结果。 |
42 | ToLongFunction<T> 接受一个输入参数,返回一个long类型结果。 |
43 | UnaryOperator<T> 接受一个参数为类型T,返回值类型也为T。 |
函数式接口举例
demo1 Function<T,R>
java.util.function.Function<T, R>接口定义了一个叫作apply的方法,它接受一个 泛型T的对象,并返回一个泛型R的对象。如果你需要定义一个Lambda,将输入对象的信息映射到输出,就可以使用这个接口。
package com.common;
import java.util.Date;
import java.util.function.Function;
public class FunctionInterfaceTest {
/**
* 如果你想把接受一些输入参数并将对输入参数处理过后的结果返回的功能封装到一个方法内,Function接口是一个不错的选择。
* 输入的参数类型和输出的结果类型可以一致或者不一致。
*
* @param valueToBeOperated
* @param function
*/
static void modifyTheValue(int valueToBeOperated, Function<Integer, Integer> function) {
int newValue = function.apply(valueToBeOperated);
/*
* Do some operations using the new value.
*/
System.out.println(newValue);
}
public static void main(String[] args) {
Function<String, Student> function = (name) -> {
return new Student(name);
};
function = Student::new;
Student student = function.apply("sdsd");
modifyTheValue(1, (val) -> val + 100);
Function<Integer, Integer> incr100Function = (val) -> {
return val + 100;
};
Function<Integer, Integer> incr200Function = (val) -> {
return val + 200;
};
incr100Function.andThen(incr200Function);
int res = incr100Function.andThen(incr200Function).apply(1);
System.out.println(res);
}
}
class Student {
public enum Sex {
MALE, FEMALE
}
String name;
int age;
Date birthday;
Sex gender;
String emailAddress;
public Student() {
}
public Student(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Sex getGender() {
return gender;
}
public void setGender(Sex gender) {
this.gender = gender;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public Date getBirthday() {
return birthday;
}
public static Integer compareByAge(Person a, Person b) {
return a.age - b.age;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Student{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append(", birthday=").append(birthday);
sb.append(", gender=").append(gender);
sb.append(", emailAddress='").append(emailAddress).append('\'');
sb.append('}');
return sb.toString();
}
}
demo2 Consumer<T>
java.util.function.Consumer<T>定义了一个名叫accept的抽象方法,它接受泛型T 的对象,没有返回(void)。你如果需要访问类型T的对象,并对其执行某些操作,就可以使用 这个接口。比如,你可以用它来创建一个forEach方法,接受一个Integers的列表,并对其中 每个元素执行操作。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
不像其他函数式接口,Consumer接口期望执行带有副作用的操作(Consumer的操作可能会更改输入参数的内部状态)。使用方式如下,
package com.common;
import java.util.function.Consumer;
public class ConsumerInterfaceTest {
static class Task {
int status;
String name;
}
static Task task;
static {
task = new Task();
task.status = 1;
}
public static void handler(Consumer<Task> action) {
action.accept(task);
}
public static void main(String[] args) {
handler((task -> {
task.status = 0;
}));
System.out.println(task.status);
}
}
demo3 Supplier<T>
public interface Supplier<T> {
/**
* Gets a result.
* @return a result
*/
T get();
}
不接受参数,返回一个结果
package com.common;
import java.util.function.Supplier;
public class SupplierInterfaceTest {
static class Product {
String type;
double price;
public Product(String type, double price) {
this.type = type;
this.price = price;
}
}
private Supplier<Product> productSupplier = () -> {
return new Product("test", 0.01);
};
public static void main(String[] args) {
SupplierInterfaceTest supplierInterfaceTest = new SupplierInterfaceTest();
Product product = supplierInterfaceTest.productSupplier.get();
}
}
demo4 Predicate<T>
java.util.function.Predicate<T>接口定义了一个名叫test的抽象方法,它接受泛型 T对象,并返回一个boolean。在需要 表示一个涉及类型T的布尔表达式时,就可以使用这个接口。
package java.util.function;
import java.util.Objects;
/**
* Represents a predicate (boolean-valued function) of one argument.
*
*/
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*/
boolean test(T t);
/**
* Returns a composed predicate that represents a short-circuiting logical
* AND of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code false}, then the {@code other}
* predicate is not evaluated.
*
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* Returns a predicate that represents the logical negation of this
* predicate.
*
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* Returns a composed predicate that represents a short-circuiting logical
* OR of this predicate and another. When evaluating the composed
* predicate, if this predicate is {@code true}, then the {@code other}
* predicate is not evaluated.
*
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
如下示例 ,
package com.common;
import java.util.function.Predicate;
public class PredicateInterfaceTest {
static class TaskInfo {
String name;
int status;
}
private Predicate<TaskInfo> taskInfoPredicate = taskInfo -> {
return taskInfo.status == 0;
};
private Predicate<TaskInfo> taskInfoNamePredicate = taskInfo -> {
return taskInfo.name.compareTo("b") == 0;
};
public static void main(String[] args) {
TaskInfo taskInfo = new TaskInfo();
taskInfo.status = 0;
taskInfo.name = "abs";
PredicateInterfaceTest predicateInterfaceTest = new PredicateInterfaceTest();
boolean res = predicateInterfaceTest.taskInfoPredicate.test(taskInfo);
System.out.println(res);
res = predicateInterfaceTest.taskInfoPredicate.and(predicateInterfaceTest.taskInfoNamePredicate).test(taskInfo);
System.out.println(res);
}
}
=========END=========