lambda表达式:将一段代码进行赋值,或入参。
实质:佚名内部类
Runnable接口就是一个函数式接口。
常用的函数式接口:
消费型接口 BiConsumer:俩个入参,无返回值
Consumer :一个入参,无返回值
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
default BiConsumer<T, U> andThen(BiConsumer<? super T, ? super U> after) {
Objects.requireNonNull(after);
return (l, r) -> {
accept(l, r);
after.accept(l, r);
};
}
}
举例:
package learn.builder;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public class Java8Builder {
public class Person{
private String name ;
private String number ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", number='" + number + '\'' +
'}';
}
}
public Supplier<Person> getPerson = Person::new;
public BiConsumer<Person,String> changeName = (x, y)->x.setName(y);
public BiConsumer<Person,String> changeNumber = (x,y)->x.setNumber(y);
}
package learn.test;
import learn.builder.Java8Builder;
public class BuilderTest {
public static void main(String[] args) {
Java8Builder jb = new Java8Builder();
Java8Builder.Person person= jb.getPerson.get();
jb.changeName.accept(person,"zzx");
jb.changeNumber.accept(person,"001");
System.out.println(person);
}
}
供给型接口 Supplier:无参,有一个返回值
package learn.singleton;
import java.util.function.Supplier;
public enum Singleton5 {
INSTANCE;
// 使用JAVA8新特性,写单例
public static Supplier<Singleton5> getInstance(){
return ()->Singleton5.INSTANCE;
}
public void doSomething(){
System.out.println("Something is Done.");
}
}
package learn.test;
import learn.singleton.Singleton5;
public class SingletonTest {
public static void main(String[] args) {
Singleton5.getInstance().get().doSomething();
}
}
函数型接口 Function:一个入参,一个返回值
BiFunction:俩个入参,一个返回值
//根据key获取value,不存在则之心function的逻辑生成一个value
//用于延迟加载
//1.8Hash中新增的方法
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
private MapperMethodInvoker cachedInvoker(Object proxy, Method method, Object[] args) throws Throwable {
try {
return methodCache.computeIfAbsent(method, m -> {
if (m.isDefault()) {
try {
if (privateLookupInMethod == null) {
return new DefaultMethodInvoker(getMethodHandleJava8(method));
} else {
return new DefaultMethodInvoker(getMethodHandleJava9(method));
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
} else {
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
});
} catch (RuntimeException re) {
Throwable cause = re.getCause();
throw cause == null ? re : cause;
}
}
断言型接口 Predicate:一个入参,返回boolean。
BiPredicate:俩个入参,返回boolean
junit框架中大量使用
//Optional中的过滤方法
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
@Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
Optional<AnnotatedElement> element = context.getElement();
Optional<Disabled> disabled = findAnnotation(element, Disabled.class);
if (disabled.isPresent()) {
String reason = disabled.map(Disabled::value).filter(StringUtils::isNotBlank).orElseGet(
() -> element.get() + " is @Disabled");
return ConditionEvaluationResult.disabled(reason);
}
return ENABLED;
}
主要的就是这四大类型的函数式接口。
此外,我们也可以自定义我们需要的函数式接口,比如springBoot中的CommandLineRunner接口
@FunctionalInterface
public interface CommandLineRunner {
/**
* Callback used to run the bean.
* @param args incoming main method arguments
* @throws Exception on error
*/
void run(String... args) throws Exception;
}
@MapperScan("com.itw.learn.dao")
@SpringBootApplication
@Import(DynamicDataSourceRegister.class)
public class MyAppDemo {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MyAppDemo.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("来看看 SpringBoot 默认为我们提供的 Bean:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.stream(beanNames)
.filter(t->t.equals("PrimaryDatasource"))
.forEach(System.out::println);
};
}
}
另外,Stream的本质,其实就是对底层四大类型的函数式接口的应用
比如:
void forEach(Consumer<? super T> action);
Stream<T> filter(Predicate<? super T> predicate);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);