前言
这四个类都属性java.util.function包下比较常见的类,在日常的工作中大多数处理lambda的展现形式,不是明显可见的。
Supplier接口
/**
* Represents a supplier of results.
*
* <p>There is no requirement that a new or distinct result be returned each
* time the supplier is invoked.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #get()}.
*
* @param <T> the type of results supplied by this supplier
*
* @since 1.8
*/
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
官方解释:表示结果的提供者。
有点抽象,其实就是一个存储指定泛型的容器,是一个供给型的接口,其中的get方法就是用来获取存储的数据的。常在通用工具类的设计中会用到。
Supplier不需要入参,需要返参
@Test
public void SupplierTest() {
// 写法1
Supplier<String> dataA = new Supplier<String>() {
@Override
public String get() {
return "存储的数据A";
}
};
// 写法2 lambda表达式
Supplier<String> dataB = () -> "存储的数据B";
System.out.println(dataA.get());
System.out.println(dataB.get());
}
控制台
Connected to the target VM, address: '127.0.0.1:52477', transport: 'socket'
存储的数据A
存储的数据B
Disconnected from the target VM, address: '127.0.0.1:52477', transport: 'socket'
Consumer接口
/**
* Represents an operation that accepts a single input argument and returns no
* result. Unlike most other functional interfaces, {@code Consumer} is expected
* to operate via side-effects.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #accept(Object)}.
*
* @param <T> the type of the input to the operation
*
* @since 1.8
*/
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
// 其他方法暂省略
}
官方解释:表示接受单个输入参数且不返回结果的操作。
Consumer是一个消费型接口,对传入的数据进行处理,然后输出。
Stream流中的foreach中就是需要传入这个接口
Consumer需要入参,没有返参
@Test
public void ConsumerTest() {
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("我需要处理数据:" + s);
}
};
Stream<String> stream = Stream.of("A", "B", "C", "D", "E");
stream.forEach(consumer);
}
控制台
Connected to the target VM, address: '127.0.0.1:57993', transport: 'socket'
我需要处理数据:A
我需要处理数据:B
我需要处理数据:C
我需要处理数据:D
我需要处理数据:E
Disconnected from the target VM, address: '127.0.0.1:57993', transport: 'socket'
Function接口
/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
// 其他方法暂省略
}
官方解释:表示接受一个参数并产生一个结果的函数。
Function 接口是一个功能型接口,它的一个作用就是转换作用,将输入数据转换成另一种形式的输出数据。比如工作中用到的将数据库中查询出来的PO类型转化为VO或者DTO,就可以写一个公共的转化工具类,传入对应的Class类。
Stream流中的map中就是需要传入这个接口
@Test
public void FunctionTest() {
Function<String, Integer> function = new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return s.hashCode();
}
};
Stream<String> stream = Stream.of("A", "B", "C", "D", "E");
stream.map(function).forEach(System.out::println);
}
控制台
Connected to the target VM, address: '127.0.0.1:58095', transport: 'socket'
65
66
67
68
69
Disconnected from the target VM, address: '127.0.0.1:58095', transport: 'socket'
Function接口有入参,也有回参
Predicate接口
/**
* Represents a predicate (boolean-valued function) of one argument.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #test(Object)}.
*
* @param <T> the type of the input to the predicate
*
* @since 1.8
*/
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
// 其他方法暂省略
}
官方解释:表示一个参数的谓词(布尔值函数)。
Predicate 接口是一个谓词型接口,其实,这个就是一个类似于 bool 类型的判断的接口,实现其中的test方法进行判断。
Stream流中的anyMatch中就是需要传入这个接口
@Test
public void PredicateTest() {
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() > 2;
}
};
Stream<String> stream = Stream.of("AAA", "B", "C", "D", "E");
System.out.println(stream.anyMatch(predicate));
}
控制台
Connected to the target VM, address: '127.0.0.1:55164', transport: 'socket'
true
Disconnected from the target VM, address: '127.0.0.1:55164', transport: 'socket'
补充
发现Supplier接口、Consumer接口、Function接口、Predicate接口这四个都被@FunctionalInterface注解修饰。
/**
* An informative annotation type used to indicate that an interface
* type declaration is intended to be a <i>functional interface</i> as
* defined by the Java Language Specification.
*
* Conceptually, a functional interface has exactly one abstract
* method. Since {@linkplain java.lang.reflect.Method#isDefault()
* default methods} have an implementation, they are not abstract. If
* an interface declares an abstract method overriding one of the
* public methods of {@code java.lang.Object}, that also does
* <em>not</em> count toward the interface's abstract method count
* since any implementation of the interface will have an
* implementation from {@code java.lang.Object} or elsewhere.
*
* <p>Note that instances of functional interfaces can be created with
* lambda expressions, method references, or constructor references.
*
* <p>If a type is annotated with this annotation type, compilers are
* required to generate an error message unless:
*
* <ul>
* <li> The type is an interface type and not an annotation type, enum, or class.
* <li> The annotated type satisfies the requirements of a functional interface.
* </ul>
*
* <p>However, the compiler will treat any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
*
* @jls 4.3.2. The Class Object
* @jls 9.8 Functional Interfaces
* @jls 9.4.3 Interface Method Body
* @since 1.8
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}
1、该注解只能标记在"有且仅有一个抽象方法"的接口上。
2、JDK8接口中的静态方法和默认方法,都不算是抽象方法。
3、接口默认继承java.lang.Object,所以如果接口显示声明覆盖了Object中方法,那么也不算抽象方法。
4、该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错。