从面向过程编程发展到面向对象编程,现在又出现了函数式编程。
1.通过接口封装函数,传递接口实现类型对象,实现函数传递
在Java 8之前,函数作为参数传递都是通过定义封装了函数的接口实现类,然后通过封装有具体函数实现的类对象来间接实现函数的传递。
2.Java 8引入函数式编程
但是从Java 8开始,Java支持Lambda表达式和函数式编程。但实际上,Java中并不是使用的真正的函数式编程,还是沿用之前的用接口封装函数的形式,传递接口的实现类型来达到函数传递的目的。如下定义lambda表达式,实际上都是内置的接口类型的具体实现类的形式实现了函数传递:
public static void main(String[] args) {
//定义lambda表达式,必须要用实际的接口类型来接受!!!
ToIntBiFunction<Integer, Integer> integerComparator = (Integer x, Integer y) -> {
return x * (x + y);
};
//输出的结果,其实都是实际的接口类型的lambda实现类
System.out.println(integerComparator.getClass().getName());
}
结果如下:
com.example.firstdemo.tests.LambdaTest$$Lambda$14/0x0000000800066840
3.Java函数式编程的原理
为了支持函数式编程,Java8之后在java.utl.function包中定义了各种基本函数式的接口类型,用于描述各种函数对象。换句话说,各种函数对象,实际上都是这些基本函数式类型的具体实现类。
主要有四类基本组件:Function、Consumer、Predicate和Supplier。
- 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);
}
- 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);
}
- Predicate:表示接受任意类型参数,返回boolean型结果的函数类型(对参数进行断言,判断)
/**
* 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);
}
- 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();
}
4.各种扩展的函数式类型
基于上述四种类型,可以组合描述各种类型的lambda表达式或者函数类型对象!无论是lambda表达式,还是函数对象的引用都是得到了函数对象,都需要赋值给具体的函数接口类型!!!
public class LambdaTest {
public static void main(String[] args) {
//1.定义lambda表达式,必须要用实际的接口类型来接受!!!
ToIntBiFunction<Integer, Integer> integerComparator = (Integer x, Integer y) -> {
return x * (x + y);
};
//输出的结果,其实都是实际的接口类型的lambda实现类
System.out.println(integerComparator.getClass().getName());
//2.直接应用获取函数对象,必须要用实际的接口类型来接受!!!
BiConsumer<Interface, Object> showInfo = Interface::showInfo;
}
}
interface Interface {
void showInfo(Object msg);
}
基于四种基本组件扩展的函数类型描述:
5.复杂函数类型的描述
上述内容,都是通过最外层函数的参数类型和返回值类型推断出函数所属的函数接口类型,是一种逆向解析类型的思路。
但实际上,使用时往往是通过简单函数进行不断复合获取最终所需的函数,即函数式操作。而这一类,就需要四种基本组件接口中提供的函数式操作进行复合组装起来即可。
Function中有compose、andThen和identity:
@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;
}
}
Consumer中有andThen:
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
Predicate里面有,各种逻辑操作,and、not、or、negate等于或非否:
@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);
/**
* 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.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ANDed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* AND of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
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.
*
* @return 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.
*
* <p>Any exceptions thrown during evaluation of either predicate are relayed
* to the caller; if evaluation of this predicate throws an exception, the
* {@code other} predicate will not be evaluated.
*
* @param other a predicate that will be logically-ORed with this
* predicate
* @return a composed predicate that represents the short-circuiting logical
* OR of this predicate and the {@code other} predicate
* @throws NullPointerException if other is null
*/
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)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return 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);
}
/**
* Returns a predicate that is the negation of the supplied predicate.
* This is accomplished by returning result of the calling
* {@code target.negate()}.
*
* @param <T> the type of arguments to the specified predicate
* @param target predicate to negate
*
* @return a predicate that negates the results of the supplied
* predicate
*
* @throws NullPointerException if target is null
*
* @since 11
*/
@SuppressWarnings("unchecked")
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}