一、Lambda表达式
1.什么是lambda表达式
lambda表达式是一种匿名函数表达式
2.lambda表达式语法
- 无参 : ()-> expression
- 有参 :(parameters)-> {statement;}
/**
* 定义一个标签tag类
*/
class Tag {
private int tagId;
private String tagName;
private int weight;
public Tag(int tagId, String tagName, int weight) {
this.tagId = tagId;
this.tagName = tagName;
this.weight = weight;
}
public int getTagId() {
return tagId;
}
public void setTagId(int tagId) {
this.tagId = tagId;
}
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Tag{" +
"tagId=" + tagId +
", tagName='" + tagName + '\'' +
", weight=" + weight +
'}';
}
}
public class LambdaDemo {
public static void main(String[] args) {
List<Tag> tagList = new ArrayList<Tag>(10);
tagList.add(new Tag(1001, "JAVA", 15));
tagList.add(new Tag(1002, "Golang", 10));
tagList.add(new Tag(1003, "Lua", 17));
tagList.add(new Tag(1004, "PHP", 11));
tagList.add(new Tag(1005, "Node.js", 13));
/**
* 1.通过匿名函数来排序
*/
Collections.sort(tagList, new Comparator<Tag>() {
@Override
public int compare(Tag o1, Tag o2) {
if (o1.getWeight() > o2.getWeight()) {
return -1;
} else if (o1.getWeight() == o2.getWeight()) {
return 0;
} else {
return 1;
}
}
});
System.out.println(tagList); //[Tag{tagId=1003, tagName='Lua', weight=17}, Tag{tagId=1001, tagName='JAVA', weight=15}, Tag{tagId=1005, tagName='Node.js', weight=13}, Tag{tagId=1004, tagName='PHP', weight=11}, Tag{tagId=1002, tagName='Golang', weight=10}]
/**
* 2.通过lambda表达式来实现排序
*/
Collections.sort(tagList, (t1, t2)-> t2.getWeight() - t1.getWeight());
System.out.println(tagList);
}
}
二、函数式接口
1.什么是函数式接口
函数接口是一种特殊的接口,它有且仅有一个接象方法(因为java8及以后,接口可以有默认方法,因此它可以有其他的默认方法)
@FunctionalInterface
interface Sortable<T> {
public T sort(T obj);
}
如:上例中这个Sortable
接口中只有一个sort抽象方法
2.函数式接口声明
通过注解 @FunctionInterface
来声明
@FunctionalInterface
interface Testable<T> {
public boolean test(T obj);
}
3.常用的函数式接口
(1) Predicate 接口
- 主要作用:测试输入对象是否符合某个条件
- 主要方法:
- 抽象方法: test
- 默认方法
- negate : 不符合指定条件时为true
- and : 多个条件都满足
- or : 多个条件有一个满足
/**
* 1.使用传统的匿名函数
*/
Predicate<String> isNumber = new Predicate<String>() {
@Override
public boolean test(String s) {
if (s == null || s.length() < 1) {
return false;
}
return s.matches("\\d+");
}
};
/**
* 2.使用lambda表达式(是否为中包含数字的字符串)
*/
Predicate<String> isNumberString = x -> x.matches("\\d+");
/**
* 字符串是否为5位
*/
Predicate<String> isFifth = x -> x.length() == 5;
/**
* 是否只包括英文字母
*/
Predicate<String> isLetter = x -> x.matches("[A-Za-z]+");
/**
* 1.直接调用Predicate接口的test方法
*/
System.out.println(isNumber.test("123456"));
System.out.println(isNumberString.test("456"));
/**
* 2.使用and方法
*/
System.out.println(isNumber.and(isFifth).test("12345")); //true (是5位的数字字符串)
/**
* 3.使用or方法
*/
System.out.println(isNumber.or(isLetter).test("Abcd")); //true (数字或者英文字母)
System.out.println(isNumber.or(isLetter).test("Abcd14")); //false
/**
* 4.使用negate方法
*/
System.out.println(isNumber.negate().test("123456")); //false (不是数字)
System.out.println(isNumber.negate().test("ABc")); //true
(2)Supplier接口
- 主要作用:创建对象,类似于对象工厂
- 主要方法:get
Supplier<String> strSupplier = ()->"hello supplier";
System.out.println(strSupplier.get()); //hello supplier
Supplier<Record> recordSupplier = () -> new Record();
System.out.println(recordSupplier.get());
(3)Consumer接口
- 主要作用:接收一个参数,对参数进行处理,但不返回(类似于一个消费的接口,只不过不需要反馈消费结果)
- 主要方法:
- accept : 接收参数,并进行处理
- andThen : 接收另外一个Consumer接口,先处理当前接口的accept方法,再处理接收的Consumer接口
Consumer<String> stringConsumer = s -> System.out.println("accepted:"+s);
stringConsumer.accept("开奖了"); //accepted:开奖了
Consumer<String> afterConsumer = s -> System.out.println("after:"+s);
stringConsumer.andThen(afterConsumer).accept("中奖了");
/**
* accepted:中奖了
* after:中奖了
*/
(4)Function接口
- 主要作用:定义函数对象,生成一个Function对象
- 主要方法:
- apply : 将Function对象应用到输入的参数上,然后返回计算结果
- andThen : 两个函数对象进行组合操作
/**
* 游戏记录
*/
class ActivityRecord {
/**
* 记录ID
*/
private Long recordId;
/**
* 用户ID
*/
private Long userId;
/**
* 结果
*/
private Integer result;
/**
* 时长
*/
private Integer period;
/**
* 得分
*/
private Integer score;
/**
* 创建时间
*/
private Long createTime;
public ActivityRecord(Long recordId, Long userId, Integer result, Integer period, Integer score, Long createTime) {
this.recordId = recordId;
this.userId = userId;
this.result = result;
this.period = period;
this.score = score;
this.createTime = createTime;
}
public Long getRecordId() {
return recordId;
}
public void setRecordId(Long recordId) {
this.recordId = recordId;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
public Integer getPeriod() {
return period;
}
public void setPeriod(Integer period) {
this.period = period;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public Long getCreateTime() {
return createTime;
}
public void setCreateTime(Long createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "ActivityRecord{" +
"recordId=" + recordId +
", userId=" + userId +
", result=" + result +
", period=" + period +
", score=" + score +
", createTime=" + createTime +
'}';
}
}
/**
* 按创建时间由小到大排序
*/
class SortByCreateTime implements Function<List<ActivityRecord>, List<ActivityRecord>> {
@Override
public List<ActivityRecord> apply(List<ActivityRecord> activityRecordList) {
return activityRecordList.stream().sorted(Comparator.comparing(ActivityRecord::getCreateTime)).collect(Collectors.toList());
}
}
/**
* 按分数倒序排列
*/
class SortByScore implements Function<List<ActivityRecord>, List<ActivityRecord>> {
@Override
public List<ActivityRecord> apply(List<ActivityRecord> activityRecordList) {
return activityRecordList.stream().sorted(Comparator.comparing(ActivityRecord::getScore).reversed()).collect(Collectors.toList());
}
}
public class FunctionDemo {
public static void main(String[] args) {
List<ActivityRecord> recordList = new ArrayList<ActivityRecord>(5);
int now = LocalDateTime.now().getNano();
recordList.add(new ActivityRecord(1001L, 3500452001L, 1, 30, 1558, Long.valueOf(now)));
recordList.add(new ActivityRecord(1002L, 3500462001L, 0, 130, 3600, Long.valueOf(now - 1000)));
recordList.add(new ActivityRecord(1003L, 3501452001L, 0, 350, 12, Long.valueOf(now + 2000)));
recordList.add(new ActivityRecord(1004L, 3300452001L, 1, 10, 300, Long.valueOf(now - 5000)));
SortByCreateTime sortByCreateTime = new SortByCreateTime();
SortByScore sortByScore = new SortByScore();
System.out.println(sortByCreateTime.apply(recordList));
System.out.println(sortByScore.apply(recordList));
System.out.println(sortByCreateTime.andThen(sortByScore).apply(recordList));
}
}
(5)Comparator接口
- 主要作用:用于比较和排序等(后面和stream一起使用再详细说明)
三、接口默认方法
注:java8之前,接口只能包括抽象方法,不能包含实例方法或静态方法,如下
interface TagService {
/**
* 查询标签列表
* @return
*/
public List queryList();
/**
* 获取某个标签
* @param tagId
* @return
*/
public Tag get(int tagId);
/**
* 添加标签
* @param tag
* @return
*/
public int add(Tag tag);
/**
* 修改标签
* @param tag
* @return
*/
public int update(Tag tag);
/**
* 删除标签
* @param tagId
* @return
*/
public int delete(int tagId);
}
java8以后,接口不仅有抽象方法,也可以有默认方法(实例方法)和静态方法
1.接口默认方法
- 使用关键词default来修饰,在方法返回类型之前
public default returnType methodName() {
}
interface TagVService {
public default void print() {
System.out.println("hello default method");
}
}
作用:有一些默认实现的方法,不需要所有的实现都由实现类来完成
在java标准类库中有很多接口有默认方法,如比较器接口Comparator
- thenComparing : 多个比较条件
- reversed : 倒序
2.接口静态方法
接口可以像普通类一样有静态方法
interface TagVService {
public static String getDefault() {
return "default";
}
}
在java标准类库中有很多接口有静态方法,如比较器接口Comparator
- Comparator.comparing() : 比较
- Comparator.comparingInt() : 比较整数
- Comparator.comparingLong() : 比较长整数
- Comparator.comparingDouble : 比较双精度浮点数
- Comparator.naturalOrder() : 正序排列
- Comparator.reverseOrder() : 倒序排列