函數(shù)式接口
Lambda基本語法:() ->
函數(shù)式接口
- 如果一個(gè)接口只有一個(gè)抽象方法吃衅,那么該接口就是一個(gè)函數(shù)式接口骗绕。
- 如果我們?cè)谀硞€(gè)接口上聲明了
@FunctionalInterface
注解变姨,那么編譯器就會(huì)按照函數(shù)式接口的定義來要求該接口 - 如果某個(gè)接口只有一個(gè)抽象方法弦悉,但我們并沒有給該接口聲明
@FunctionalInterface
注解宇驾,那么編譯器依舊會(huì)將該接口看作是函數(shù)式接口误窖。
@FunctionalInterface
注解
通過閱讀代碼注釋我們得知:
- functional interface只能有一個(gè)抽象方法
- 如果接口重寫了
java.lang.Object
中的方法,比如toString()
猜绣,并不會(huì)增加接口的抽象方法數(shù)量
/**
* 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 {}
針對(duì)第一點(diǎn)很好理解灰殴,接口只能有一個(gè)抽象方法,我們重點(diǎn)看下第二點(diǎn)
這樣也是符合函數(shù)式接口要求的掰邢,因?yàn)?code>toString()是Object中的方法牺陶,是所有對(duì)象的父類
@FunctionalInterface
public interface MyInterface {
void test();
@Override
String toString();
}
public static void main(String[] args) {
MyInterface myInterface = () -> {
System.out.println("myInterface");
};
System.out.println("我的類型是:"+ myInterface.getClass());
System.out.println("我的父類是:"+ myInterface.getClass().getSuperclass());
System.out.println("我的父類是:"+ myInterface.getClass().getSuperclass());
System.out.println("我的抽象方法數(shù)量是:"+ myInterface.getClass().getInterfaces().length);
System.out.println("我的抽象方法是:"+ myInterface.getClass().getInterfaces()[0]);
}
輸出信息:
我的類型是:class a.Test$$Lambda$1/990368553
我的父類是:class java.lang.Object
我的父類是:class java.lang.Object
我的抽象方法數(shù)量是:1
我的抽象方法是:interface a.MyInterface
Jdk8提供的函數(shù)式接口
Consumer
消費(fèi)一個(gè)數(shù)據(jù)
代表了接受一個(gè)輸入?yún)?shù)并且無返回的操作
Consumer.accept(T t) 接收一個(gè)需要處理的數(shù)據(jù)對(duì)象伟阔,有參數(shù),無返回值
Consumer.andThen(Consumer<? super T> after) 接收一個(gè)Consumer繼續(xù)處理
@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); };
}
}
例子
public static void main(String[] args) {
consumer("我們是一只小小的鳥掰伸, 鳥呀皱炉!", s -> {
System.out.println("處理后字符串:" + s.replace("鳥", "人"));
});
}
public static void consumer(String s1, Consumer<String> s2) {
System.out.println("原始字符串:"+ s1);
s2.accept(s1);
s2.andThen(s2);
}
Function
輸入T輸出R
接受一個(gè)輸入?yún)?shù),返回一個(gè)結(jié)果
R apply(T t)
有參數(shù)狮鸭,有返回值
compose()
先調(diào)用compose合搅,在執(zhí)行調(diào)用者
andThen
先執(zhí)行調(diào)用者,在執(zhí)行andThen
/**
* 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);
/**
* Returns a composed function that first applies the {@code before}
* function to its input, and then applies this function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of input to the {@code before} function, and to the
* composed function
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
* @throws NullPointerException if before is null
*
* @see #andThen(Function)
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
/**
* Returns a composed function that first applies this function to
* its input, and then applies the {@code after} function to the result.
* If evaluation of either function throws an exception, it is relayed to
* the caller of the composed function.
*
* @param <V> the type of output of the {@code after} function, and of the
* composed function
* @param after the function to apply after this function is applied
* @return a composed function that first applies this function and then
* applies the {@code after} function
* @throws NullPointerException if after is null
*
* @see #compose(Function)
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
}
例子
public class Test3 {
private static void method_andThen(Function<String, String> f1, Function<String, String> f2) {
String apply = f1.andThen(f2).apply("先執(zhí)行調(diào)用者;第二章:");
System.out.println(apply);
}
private static void method_compose(Function<String, String> f1, Function<String, String> f2) {
String apply = f1.compose(f2).apply("先調(diào)用compose歧蕉;第二章:");
System.out.println(apply);
}
public static void main(String[] args) {
numberToString((s) -> String.valueOf(s));
// 第二章:天下皆知美之為美 斯惡已
method_andThen(s -> s += "天下皆知美之為美 ", s -> s += " 斯惡已");
// 第二章:斯惡已 天下皆知美之為美
method_compose(s -> s += " 天下皆知美之為美 ", s -> s += "斯惡已");
// 輸入對(duì)象就是輸出對(duì)象
Object apply = Function.identity().apply("test");
System.out.println(apply);
}
/**
* 將數(shù)字轉(zhuǎn)換為String類型
* @param function
*/
private static void numberToString(Function<Number, String> function) {
String apply = function.apply(12);
System.out.println("轉(zhuǎn)換結(jié)果:" + apply);
}
}
Predicate
斷定型接口
接收參數(shù)T灾部,返回boolean,用來確定T類型參數(shù)是否滿足某約束惯退,并返回boolean值
處理集合的過濾條件
@FunctionalInterface
public interface Predicate<T> {
/**
* 具體過濾操作 需要被子類實(shí)現(xiàn).
* 用來處理參數(shù)T是否滿足要求,可以理解為 條件A
*/
boolean test(T t);
/**
* 調(diào)用當(dāng)前Predicate的test方法之后再去調(diào)用other的test方法,相當(dāng)于進(jìn)行兩次判斷
* 可理解為 條件A && 條件B
*/
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
/**
* 對(duì)當(dāng)前判斷進(jìn)行"!"操作,即取非操作赌髓,可理解為 ! 條件A
*/
default Predicate<T> negate() {
return (t) -> !test(t);
}
/**
* 對(duì)當(dāng)前判斷進(jìn)行"||"操作,即取或操作,可以理解為 條件A ||條件B
*/
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
/**
* 對(duì)當(dāng)前操作進(jìn)行"="操作,即取等操作,可以理解為 A == B
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
舉例
public class TestPredicate {
public static void main(String[] args) {
Predicate<String> predicate = (s) -> s.length() > 5;
boolean r = predicate.test("12346");
// true
System.out.println(r);
// 在Stream中使用
List<User> userList = initUserData();
// User{name='狗', age='5'}
// User{name='烏龜', age='200'}
userList.stream().filter(u -> u.getAge() >= 5).forEach(System.out::println);
}
public static List<User> initUserData() {
List<User> userList = new ArrayList<>();
userList.add(new User("貓", 2));
userList.add(new User("狗", 5));
userList.add(new User("烏龜", 200));
return userList;
}
static class User {
private String name;
private Integer age;
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
}
Supplier
提供數(shù)據(jù)的函數(shù)式接口
生產(chǎn)數(shù)據(jù)
T get();
每個(gè)調(diào)用都會(huì)新創(chuàng)建一個(gè)對(duì)象
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
舉例
public class TestSupplier {
public static void main(String[] args) {
Supplier<User> user = User::new;
User user1 = user.get();
User user2 = user.get();
// 1747585824
System.out.println(user1.hashCode());
// 1023892928
System.out.println(user2.hashCode());
}
static class User {
private String name;
private Integer age;
public User() {}
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
}