文章目录
学习总结自《java核心技术卷一》
1.函数式接口
我们前面已经说到,lambda表达式其实就是对接口方法的快速实现。
那是不是所有的接口方法都能让lambda表达式快速实现呢? 答案是否定的,
lambda表达式只能对特殊的接口方法进行快速实现,那就是函数式接口,lambda表达式能对函数式接口的方法进行快速实现。
1.1 什么是函数式接口?
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式替代对象,这样的接口我们称之为
函数式接口(functional interface)
。(有的接口可能重新声明Object类的方法,这些声明可能会让方法不再是抽象的,且在javaSE8中,接口可以声明非抽象方法)
1.2 如何用lambda表达式替代?
我们以下面的例子来理解:
Arrays.sort(words,(first,second)->first.length()-second.length());
上面使用了Arrays.sort()方法,它的第二个参数需要一个Comparator的实例,而Comparator就是只有一个抽象方法的接口,
int compare(T o1, T o2);
所以我们可以用lambda表达式
(first,second)->first.length()-second.length()
替代它
我们要记住:把lambda表达式看作是一个函数,而且lambda表达式可以传递到函数式接口中去
实际上,在Java中lambda表达式所能做的也只能是转换为函数式接口:
例如下面的函数式接口
public interface ActionListener extends EventListener {
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent e);
}
使用它
Timer t= new Timer(1000,(evnet)->
{
System.out.println("At the tone,the time is"+new Date());
Toolkit.getDefaultToolkit().beep();
});
上面代码与使用实现了ActionListener接口的类相比,这个代码可读性要好很多。
演示:
public static void main(String[] args) throws InterruptedException {
Timer t = new Timer(1000, event->{
System.out.println("At the tone,the time is"+new Date());
Toolkit.getDefaultToolkit().beep();
});
t.start();
JOptionPane.showMessageDialog(null,"要退出吗?");
System.exit(0);
}
1.3 Java中常用函数式接口
Java API在java.util.function包中定义了很多非常通用的函数式接口。
1.3.1 Runnable接口
@FunctionalInterface
public interface Runnable {
//抽象方法
public abstract void run();
}
这个接口典型的应用场景就是多线程编程,它没有出参和入参,也没有泛型参数。
使用实例:
public void runnableStudy(Runnable runnable){
runnable.run();
}
//测试
functionStudy.runnableStudy(()->{
System.out.println("使用Runnable的lambada表达式打印这句话的");
});
1.3.2 Supplier接口
@FunctionalInterface
public interface Supplier<T> {
T get();
}
可以看到,这个接口没入参,定义了一个泛型出参,我们可以根据需求去使用它。
例如:
public void supplierStudy(Supplier<String> stringSupplier){
System.out.println(stringSupplier.get());
}
1.3.3 Consumer接口
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
这个接口提供了一个泛型入参,无出参的方法。
public void consumerStudy(String param,Consumer<String> stringConsumer){
stringConsumer.accept(param);
}
1.3.4 BiConsumer接口
@FunctionalInterface
public interface BiConsumer<T, U> {
/**
* Performs this operation on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
*/
void accept(T t, U u);
}
此函数式接口提供了两个泛型入参,无出参。
例如:
public void biConsumerStudy(String u, String t,
BiConsumer<String,String> biConsumer){
biConsumer.accept(u,t);
}
1.3.5 Function接口
@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);
}
public void functionStudy(String t,Function<String,String> function){
System.out.println(function.apply(t));
}
1.3.6 BiFunction接口
@FunctionalInterface
public interface BiFunction<T, U, R> {
/**
* Applies this function to the given arguments.
*
* @param t the first function argument
* @param u the second function argument
* @return the function result
*/
R apply(T t, U u);
}
public void biFunctionStudy(String t, String u, BiFunction<String,String,String> biFunction){
System.out.println(biFunction.apply(t,u));
}
1.3.7 UnaryOperator接口
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
/**
* Returns a unary operator that always returns its input argument.
*
* @param <T> the type of the input and output of the operator
* @return a unary operator that always returns its input argument
*/
static <T> UnaryOperator<T> identity() {
return t -> t;
}
}
public void unaryOperatorStudy(String s,UnaryOperator<String> unaryOperator){
System.out.println(unaryOperator.apply(s));
}
1.3.8 BinaryOperator接口
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
}
public void binaryOperatorStudy(String s,String t,BinaryOperator<String> binaryOperator){
System.out.println(binaryOperator.apply(s,t));
}
1.3.9 Predicate接口
@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);
}
public void predicateStudy(String s,Predicate<String> predicate){
if(predicate.test(s)){
System.out.println("正确!!!!");
}
}
1.3.10 BiPredicate接口
@FunctionalInterface
public interface BiPredicate<T, U> {
/**
* Evaluates this predicate on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
* @return {@code true} if the input arguments match the predicate,
* otherwise {@code false}
*/
boolean test(T t, U u);
}
public void biPredicateStudy(String t,String u,BiPredicate<String,String> biPredicate){
if(biPredicate.test(t,u)){
System.out.println("正确!!");
}
}
1.3.11 测试实例
public static void main(String[] args) {
FunctionStudy functionStudy = new FunctionStudy();
//无入参,出参lambda表达式
functionStudy.runnableStudy(()->{
System.out.println("使用Runnable的lambada表达式打印这句话的");
});
//无入参,有出参lambda表达式
functionStudy.supplierStudy(()->{
return "使用Supplier的lambada表达式打印这句话的";
});
//一个入参,无出参lambda表达式
functionStudy.consumerStudy("consumerStudy",(s)->{
if(s.contains("consumer")){
System.out.println(s);
}
});
//两个入参,无出参lambda表达式
functionStudy.biConsumerStudy("BiConsumerStudy","two",(s,t)->{
System.out.println(s+t);
});
//一个入参,有出参lambda表达式
functionStudy.functionStudy("functionStudy",(s)->{
return s+"test";
});
//两个入参,一个出参lambda表达式
functionStudy.biFunctionStudy("bi","Function",(s,u)->{
return s+u;
});
//一个入参,一个出参lambda表达式
functionStudy.unaryOperatorStudy("s",(s)->{
return s;
});
//两个入参,一个出参lambda表达式
functionStudy.binaryOperatorStudy("binary","Operation",(s,v)->{
return s+v;
});
//一个入参,指定boolean类型出参lambda表达式
functionStudy.predicateStudy("isGood",(s)->{
return s.contains("ood");
});
//两个入参,指定boolean类型出参lambda表达式
functionStudy.biPredicateStudy("bi","Predicate",(t,u)->{
if(t.equals("bi")&&u.contains("cate")){
return true;
}else
return false;
});
}
1.4 如何使用函数式接口
想要用lambda表达式做某些处理,还是要谨记表达式的用途,正确使用函数式接口,个人觉得Jdk中提供的一些函数式接口以及够用。
例如:java.util.function包中有一个接口:
public interface Predicate<T>{
boolean test(T t);
}
ArrayList类有一个removeIf方法,它的参数就是一个Predicate。
public boolean removeIf(Predicate<? super E> filter)
这个接口专门用来传递lambda表达式。如:
list.removeIf(e->e==null);
上面的语句表示从一个数组列表删除所有的null值。
2 完整代码仓库地址
Java基础学习/src/main/java/Progress/exa31_2/FunctionStudy.java · 严家豆/Study – 码云 – 开源中国 (gitee.com)