基于Consumer接口、Predicate接口初使用
Consumer 接口
源码
package java.util.function;
import java.util.Objects;
@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); };
}
}
从源码中可以得到,Consumer 接口是函数式接口,并且这个函数式接口的唯一抽象方法是没有返回值的,也许大家会有疑惑,没有返回值,那这个接口有什么用呢?当然,这个接口不会给我们返回什么值,但是我们可以用来修改传递过来的参数啊,这样比直接修改又多了什么优点呢?额,自己挖坑?我也说不上来多了什么优点,我还很弱,不过我喜欢这种编程方式。
直接使用 accept()
举个例子,假如用户的 name 为 null,那么就可以给他设置一个默认的 name ,想不到好的例子,感觉这个例子不是很合理,但是意思差不多。
User.java:
package entity;
public class User {
// 用户默认名字
public static final String DEFAULT_NAME = "Kaven";
// 用户的年龄
private int age;
// 用户的名字
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
testConsumer.java:
package test;
import entity.User;
import java.util.function.Consumer;
public class testConsumer{
public static void main(String[] args){
Consumer<User> consumer = user -> user.setName(User.DEFAULT_NAME);
User user = new User();
if(user.getName() == null) consumer.accept(user);
System.out.println(user.getName());
}
}
输出:Kaven
使用 andThen()
从源码可以得到,this 进行 accept() 后,after 再进行 accept(),相当于进行了两次 accept() 。
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
下面以小学成绩单为例,假设小学成绩单是由两门单科成绩(语文、数学)和总分组成,当我们需要修改其中一门成绩的时候,我们是不是也需要修改总分呢?这是肯定的啊。当然,这个例子也不是很合理。
Grade.java:
package entity;
public class Grade {
// 语文成绩
private int chinese_language;
// 英语成绩
private int english;
// 总分
private int total_score;
public Grade(int chinese_language, int english){
this.chinese_language = chinese_language;
this.english = english;
this.total_score = chinese_language + english;
}
public int getChinese_language() {
return chinese_language;
}
public void setChinese_language(int chinese_language) {
this.chinese_language = chinese_language;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getTotal_score() {
return this.total_score;
}
public void setTotal_score() {
this.total_score = this.chinese_language + this.english;
}
}
testConsumerAndThen.java:
package test;
import entity.Grade;
import java.util.function.Consumer;
public class testConsumerAndThen {
public static void main(String[] args){
Consumer<Grade> total_score = grade -> {
grade.setTotal_score();
};
Consumer<Grade> english = grade -> {
grade.setEnglish(80);
};
Grade grade = new Grade(80,70);
System.out.printf("英语成绩为:%d\n",grade.getEnglish());
System.out.printf("总分为:%d\n",grade.getTotal_score());
english.andThen(total_score).accept(grade);
System.out.println("修改英语成绩后---------------");
System.out.printf("英语成绩为:%d\n",grade.getEnglish());
System.out.printf("总分为:%d\n",grade.getTotal_score());
}
}
输出:
英语成绩为:70
总分为:150
修改英语成绩后---------------
英语成绩为:80
总分为:160
Predicate 接口
源码
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
Predicate 接口也是函数式接口,调用接口的 test 方法会返回一个布尔类型的值,其实从 Predicate 接口的源码中也可以看出来,这个接口的用处是什么。
以我的理解,是可以用来判断传递过来的参数是否匹配一些条件。
使用 test()
我们还是使用 Consumer 接口的例子,当用户的 name 为 null 时,给用户设置默认的 name。
我们可以用 Predicate 接口来判断用户的 name 是否为空,可能看起来比直接比较麻烦一点。
testPredicate.java:
package test;
import entity.User;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class testPredicate {
public static void main(String[] args){
Consumer<User> consumer = user -> user.setName(User.DEFAULT_NAME);
Predicate<User> predicate = user -> {
return user.getName() == null ;
};
User user = new User();
if(predicate.test(user)) consumer.accept(user);
System.out.println(user.getName());
}
}
输出:Kaven
一样的效果。
使用 negate()
从源码中可以得到,negate() 是返回一个对 test() 的结果取一次反的 Predicate 实例。
default Predicate<T> negate() {
return (t) -> !test(t);
}
也可以这样用,负负得正不是吗。
if(!predicate.negate().test(user)) consumer.accept(user);
使用 and()
and() 返回一个对两个 test() 以 && 的方式的 Predicate 实例。
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
在 User.java 里面加一个用户默认年龄属性。
// 用户默认年龄
public static final int DEFAULT_AGE = 20;
当用户年龄不符合情况并且名字为空时,就重新设置用户的年龄和名字。
testPredicate.java:
package test;
import entity.User;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class testPredicate {
public static void main(String[] args){
Consumer<User> consumer = user -> user.setName(User.DEFAULT_NAME);
Consumer<User> consumer_age = user -> user.setAge(User.DEFAULT_AGE);
Predicate<User> predicate = user -> {
return user.getName() == null ;
};
Predicate<User> predicate_age = user -> {
int age = user.getAge();
return (age <= 0 || age >=150);
};
User user = new User();
if(predicate.and(predicate_age).test(user)) consumer.andThen(consumer_age).accept(user);
System.out.println(user.getName());
System.out.println(user.getAge());
}
}
输出:
Kaven
20
Predicate接口还有两个方法:
or()
or() 方法应该很容易理解,or() 返回一个对两个 test() 以 || 的方式的 Predicate 实例。
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
isEqual()
接口的静态方法,看源码也很容易理解,生成一个判断是否与 targetRef equal的 Predicate 实例。targetRef 不为 null 时,如果 targetRef 这个实例的类中没有重载 Object 类的 equals() 方法或者 targetRef 这个实例本身就是 Object 类的实例,就会使用 Object 类的 equals() 进行判断,就只会判断传递过来的参数的引用是否与 targetRef 一样,和 == 相同。
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
从 Object 类的源码也很容易看出来,equals() 就是直接使用的 == 进行判断的。
public boolean equals(Object obj) {
return (this == obj);
}
要想使用自己的 equals() 进行判断,就在 targetRef 实例的类中重写 equals() 方法。
比如在 User.java 中重写 equals():
@Override
public boolean equals(Object obj) {
if(obj == null) return false;
else{
if(obj instanceof User){
User user = (User) obj;
// String 类已经重载了 equals()
if(this.name.equals((user).name) && this.age == user.age) return true;
else return false;
}
else return false;
}
}
使用 or()、isEqual()
package test;
import entity.User;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class testPredicate {
public static void main(String[] args){
Consumer<User> consumer = user -> user.setName(User.DEFAULT_NAME);
Consumer<User> consumer_age = user -> user.setAge(User.DEFAULT_AGE);
Predicate<User> predicate = user -> {
return user.getName() == null ;
};
Predicate<User> predicate_age = user -> {
int age = user.getAge();
return (age <= 0 || age >=150);
};
User user = new User();
user.setAge(21);
if(predicate.or(predicate_age).test(user)) consumer.andThen(consumer_age).accept(user);
// if(predicate.and(predicate_age).test(user)) consumer.andThen(consumer_age).accept(user);
// if(!predicate.negate().test(user)) consumer.accept(user);
// if(predicate.test(user)) consumer.accept(user);
User user_equal = new User(User.DEFAULT_AGE , User.DEFAULT_NAME);
System.out.println(Predicate.isEqual(user).test(user_equal));
System.out.println(user.equals(user_equal));
System.out.println(user.getName());
System.out.println(user.getAge());
}
}
输出:
true
true
Kaven
20
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341