目录
[三、函数式接口Functional Interface](#三、函数式接口Functional Interface)
[1. 作用](#1. 作用)
[2. 内置函数式接(Built-in Functional Interfaces)](#2. 内置函数式接(Built-in Functional Interfaces))
[1. Filter 过滤](#1. Filter 过滤)
[2. Sorted 排序](#2. Sorted 排序)
[3. Map 映射](#3. Map 映射)
[4. Match 匹配](#4. Match 匹配)
[5. Collect收集](#5. Collect收集)
[6. Statistics 统计](#6. Statistics 统计)
[7. 函数式接口总结](#7. 函数式接口总结)
[1. 格式化](#1. 格式化)
[2. 字符串转日期格式](#2. 字符串转日期格式)
[3. 日期计算](#3. 日期计算)
[4. 获取指定日期](#4. 获取指定日期)
一、Java8中Interface接口
Java8 中,接口中除了抽象方法外,还可以定义default默认方法 和 static 静态方法。
default修饰的默认方法,属于实例方法,可以被实现类调用或重写。
调用:实现类必须 implements 接口,才能调用该接口的 default 默认方法。
重写 :实现类 implements不同接口时,接口中存在相同签名的方法(名称、参数、类型完全一致),则实现类必须重写该方法明确方法定义;
static 修饰的静态方法,属于类的静态方法。但它不能被子类继承,只能用 interface 接口名称调用。
二、lambda表达式
Lambda表达式本质 是一个匿名函数 ,用于把函数作为参数,传入方法中,实现函数式编程风格。
使用 Lambda表达式可以使代码变的更加简洁紧凑。
语法格式
(parameters)->expression或(parameters)->{statements;}
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("s","sjv","safa","safth"));
// Comparator接口的匿名实现方式(传统)
// list.sort(new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length()-o2.length();
// }
// });
// lambda表达式的语法规则:(参数) -> {方法实现逻辑}
// 使用lambda表达式,@FunctionalInterface接口,只有一个抽象方法(无方法体)
// 通过lambda表达式实现Comparator接口
list.sort((s1, s2) -> {
return s1.length()-s2.length();
});
// 通过lambda表达式实现Consumer接口
list.forEach((str)->{
System.out.println(str.toUpperCase());
});
System.out.println(list);
}
三、函数式接口Functional Interface
只有一个抽象方法的接口(可以定义多个非抽象方法)。可以使用 @FunctionalInterface 接
口定义,强化语义规范。
函数式接口,也被称为SAM接口(Single Abstract Method Interfaces)。
1. 作用
基于函数式接口,可以使用Lambda 表达式进行实现,实现函数式编程。
2. 内置函数式接(Built-in Functional Interfaces)
在 Java 8中专门有一个包放函数式接口 java.util.function ,该包下的所有接口都有 @FunctionalInterface 注解,提供函数式编程方式。
Predicate接口
Predicate 接口是只有一个参数的返回布尔类型值的断言型 接口。该接口包含多种默认方法来将Predicate 组合成其他复杂的逻辑 (比如:与 and,或or,非negate)。
public static void main(String[] args) {
// Predicate predicate = new Predicate() {
// @Override
// public boolean test(Object o) {
// return false;
// }
// };
List<String> arrayList = new ArrayList<>(Arrays.asList("Basic","QBasic","c","c++","PowerBuilder","go"));
// 查找名称小于3个字符的元素
Predicate<String> predicate1 = (lang)-> {
if (lang.length()<=3) {
return true;
}
return false;
};
// 查询前缀以"b"或"c"开头的元素
Predicate<String> predicate2 = (lang)->{
if (lang.toLowerCase().startsWith("b")||lang.toLowerCase().startsWith("c")){
return true;
}
return false;
};
// 条件组合:形成"与" 或 "或"逻辑关系
Predicate<String> predicate3 = predicate1.and(predicate2);
Predicate<String> predicate4 = predicate1.or(predicate2);
// "非"逻辑 (取反)
Predicate<String> predicate5 = predicate1.negate(); // >3
arrayList.forEach((lang)->{
if (predicate1.test(lang)){
System.out.println(lang);
}
});
}
Function
Function 接口接受一个参数并生成结果。默认方法可用于将多个函数链接 在一起(compose,andThen)。
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("Basic", "QBasic", "c", "c++", "PowerBuilder", "go"));
// Function<参数类型,返回值类型>
// 转换成大写字母形式
Function<String, String> fun1 = (lang) -> {
lang = lang.toUpperCase();
return lang;
};
// 加上【】
Function<String, String> fun2 = (lang) -> {
lang = String.format("【%s】", lang);
return lang;
};
// 组合
Function<String, String> fun3 = fun1.andThen(fun2); //先fun1,后fun2
Function<String,String> fun4 = fun1.compose(fun2);
list.forEach((lang) -> {
String ret = fun3.apply(lang);
System.out.println(ret);
});
}
Comparator
比较器接口,用于比较指定元素值的大小。 Java 8版本中,添加了多个新的 default 方法,用于比较器合并、反转等操作。
public static void main(String[] args) {
List<String> list = Arrays.asList("Basic", "QBasic", "c", "c++", "PowerBuilder", "to","go");
Comparator<String> comparator1 = (lang1, lang2) -> {
int ret = lang1.compareTo(lang2);
if (ret ==0){
return lang1.length()-lang2.length();
}
return ret;
};
Comparator<String> comparable2 = comparator1.reversed(); // 反转
list.sort(comparable2);
list.forEach((lang)->{
System.out.println(lang);
});
}
四、Stream
java.util.Stream表示能应用在一组元素上一次执行的操作序列。
Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回 stream 本身,可以连续完成多个操作。
1. Filter 过滤
过滤通过一个 predicate 接口来过滤并只保留符合条件的元素,该操作属于中间操作 。所以过滤后的结果,可以继续进行其它 stream操作(例如forEach,forEach需要一个函数来对过滤后的元素依次执行。 forEach 是一个最终操作)。
public static void main(String[] args) {
Stream<String> stream = Stream.of("Basic", "QBasic", "c", "c++", "PowerBuilder", "go", "BuilderPower");
// 过滤所有小写字母内容的元素,并排序
stream.filter((lang) -> {
for (int i = 0; i < lang.length(); i++) {
char c = lang.charAt(i);
if (c > 'A' && c < 'Z') {
return true;
}
}
return false;
}).sorted((c1, c2) -> {
if (c1.length() == c2.length()) {
return c1.compareTo(c2);
} else {
return c1.length() - c2.length();
}
}).forEach((lang) -> {
System.out.println(lang);
});
}
2. Sorted 排序
排序 是一个 中间操作,返回的是排序好后的Stream 。(不影响原数据)
public static void main(String[] args) {
Stream<String> stream = Stream.of("Basic", "QBasic", "c", "c++", "PowerBuilder", "go", "BuilderPower");
// 过滤所有小写字母内容的元素,并排序
stream.filter((lang) -> {
for (int i = 0; i < lang.length(); i++) {
char c = lang.charAt(i);
if (c > 'A' && c < 'Z') {
return true;
}
}
return false;
}).sorted((c1, c2) -> {
if (c1.length() == c2.length()) {
return c1.compareTo(c2);
} else {
return c1.length() - c2.length();
}
}).forEach((lang) -> {
System.out.println(lang);
});
}
3. Map 映射
映射 是一个中间操作,会将元素根据指定的 Function 接口来依次将元素转成另外的对象。
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(10, 20, 30, 40, 50, 60);
// 映射:对每一个元素进行一次处理
stream.map((n) -> {
return n + 1;
}).forEach((n) -> {
System.out.println(n);
});
List<String> stringList = Arrays.asList("afa", "asf", "afsa");
//转换字符串为大写,降序后输出
stringList.stream().map((item) -> {
return item.toUpperCase();
}).sorted((s1, s2) -> {
return s1.compareTo(s2);
}).forEach((item) -> {
System.out.println(item);
});
}
4. Match 匹配
Stream 提供了多种匹配操作,允许检测指定的 Predicate 是否匹配整个 Stream 。所有的匹配 操作都是 最终操作 ,并返回一个boolean 类型的值。
public static void main(String[] args) {
List<String> stringList = Arrays.asList("gds","asfa","das");
// allMatch:所有元素是否匹配
boolean bool1 = stringList.stream().allMatch((item) -> {
return item.length() == 3;
});
System.out.println(bool1);
// anyMatch:任意元素是否匹配
boolean bool2 = stringList.stream().anyMatch((item) -> {
return item.length() == 3;
});
System.out.println(bool2);
}
5. Collect收集
收集 是一个 最终操作,返回 stream 中元素集合,返回值类型是集合(List、set、Map)或 字符串。
public static void main(String[] args) {
List<String> stringList = Arrays.asList("1556","5612","8489");
//将Stream流中的每个元素进行mapping映射操作后,然后收集至一个List集合
//Collectors.mapping
List<Integer> numberInt = stringList.stream().collect(Collectors.mapping(s -> Integer.parseInt(s) * 10, Collectors.toList()));
System.out.println(numberInt);
// 分组操作
// Collectors.groupingBy
// 按照元素的字符长度进行分组
Stream<String> stream = Stream.of("Basic", "QBasic", "c", "c++", "PowerBuilder", "go","BuilderPower");
Map<Integer, List<String>> resultMapGroup1 = stream.collect(Collectors.groupingBy(s -> s.length()));
resultMapGroup1.forEach((k,v)->{
System.out.println(k+":"+v);
});
// stream.collect(Collectors.groupingBy((s->s.length()))).forEach((k,v)->{
// System.out.println(k+":"+v);
// });
// 按照元素的首字母进行分组
stream = Stream.of("Basic", "QBasic", "c", "c++", "PowerBuilder", "go","BuilderPower");
stream.collect(Collectors.groupingBy(s->s.charAt(0))).forEach((k,v)->{
System.out.println(k+":"+v);
});
}
public static void main(String[] args) {
Stream<String> stream = Stream.of("Basic", "QBasic", "c", "c++", "PowerBuilder", "go","BuilderPower");
// 分区操作(只有true和false)
stream.collect(Collectors.partitioningBy(s->s.length()>3)).forEach((k,v)->{
System.out.println(k+":"+v);
});
}
6. Statistics 统计
统计 是一个最终操作,返回 Stream中元素的各类统计信息,返回值类型是 XXXConsumer。
public static void main(String[] args) {
//统计操作
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
// Stream ===> IntStream
IntStream intStream = list.stream().mapToInt(s -> s*10);
IntSummaryStatistics statisticsResult = intStream.summaryStatistics();
// 获取统计结果
System.out.println("最大值:"+statisticsResult.getMax());
System.out.println("最小值:"+statisticsResult.getMin());
System.out.println("平均值:"+statisticsResult.getAverage());
System.out.println("累加和:"+statisticsResult.getSum());
}
7. 函数式接口总结
a. Predicate、Function、Consumer、Comparator
b. 通过链式编程,使得它可以方便地对数据进行链式处理。
c. 方法参数都是函数式接口类型
d. 一个stream 只能操作一次,操作完就关闭了,继续使用这个 stream会报错。Stream不保存数据,不改变数据源。
五、日期时间
- LocalDateTime //日期+时间 format: yyyy-MM-ddTHH:mm:ss.SSS
- LocalDate //日期 format: yyyy-MM-dd
- LocalTime //时间 format: HH:mm:ss
1. 格式化
public static void main(String[] args) {
// 日期格式化
// 默认格式: yyyy-MM-dd
LocalDate date = LocalDate.now();
System.out.println(String.format("Date Format:%s",date));
// 默认格式:HH:mm:ss
LocalTime time =LocalTime.now().withNano(0);
System.out.println(String.format("Time Format:%s",time));
LocalDateTime dateTime = LocalDateTime.now();
// 自定义格式:yyyy-MM-dd HH:mm:ss
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String dateTimeStr = dateTime.format(dateTimeFormatter);
System.out.println(String.format("DateTime Format:%s",dateTimeStr));
}
2. 字符串转日期格式
public static void main(String[] args) {
// 字符串格式的日期内容,转换为LocalDate等之类的日期对象
// 按照指定的日期的时间域值进行转换
LocalDate date1 = LocalDate.of(2024,9,11);
System.out.println(date1);
// 按照默认格式(yyyy-MM-dd)的字符串,使用parse()方法进行转换
LocalDate date2 = LocalDate.parse("2024-09-11");
System.out.println(date2);
// 按照默认格式(yyyy-MM-ddTHH:mm:ss)
LocalDateTime dateTime1 = LocalDateTime.of(2024,9,11,17,50,30);
LocalDateTime dateTime2 =LocalDateTime.parse("2024-09-11T17:50:30");
System.out.println(dateTime1);
System.out.println(dateTime2);
// 按照默认格式(HH:mm:ss)
LocalTime time1 = LocalTime.of(17,50,30);
LocalTime time2 =LocalTime.parse("17:50:30");
System.out.println(time1);
System.out.println(time2);
}
3. 日期计算
public static void main(String[] args) {
// 字符串格式的日期时间
String strDatetime ="2024年12月15日";
// 将字符串格式的日期,转换为LocalDate类型的日期对象
LocalDate date = LocalDate.parse(strDatetime, DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
System.out.println(date);
// 20天前
LocalDate date1 = date.plusDays(-20);
System.out.println(date1);
//20天后
LocalDate date2 = date.plusDays(20);
System.out.println(date2);
}
public static void main(String[] args) {
//计算两个日期间隔多少天,计算间隔多少年,多少月
LocalDate date1 = LocalDate.parse("2024-07-12");
LocalDate date2 = LocalDate.parse("2024-09-11");
Period period =Period.between(date1,date2);
System.out.println("date1到date2相间隔"+period.getYears()+"年"+period.getMonths()+"月"+period.getDays()+"天");
long day = date2.toEpochDay() - date1.toEpochDay();
System.out.println(date2+"和"+date1+"相差"+day+"天");
}
4. 获取指定日期
public static void main(String[] args) {
LocalDate today = LocalDate.now();
//获取当前月第一天
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("当前月第一天:"+firstDayOfThisMonth);
//获取本月最后一天
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("当前月最后一天:"+lastDayOfThisMonth);
// 获取下一天
LocalDate nextDay = lastDayOfThisMonth.plusDays(1);
System.out.println("下一天(次月第一天):"+nextDay);
LocalDate nextDay2 = today.plusDays(1);
System.out.println("当前下一天:"+nextDay2);
//获取当年最后一天
LocalDate lastday = today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("当年最后一天:"+lastday);
//获取当年最后一个周
LocalDate lastMondayOfThisYear = lastday.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY));
System.out.println("当年最后一个周一:"+lastMondayOfThisYear);
}