目录
3.1 内置函数式接口 (Built-in Functional Interfaces)
一、Interface接口
Java8中,接口中除了抽象方法外,还可以定义default默认方法和static静态方法。
- default修饰的默认方法,属于实例方法,可以被实现类调用或重写。
- 调用:实现类必须implements接口,才能调用该接口的default默认方法。
- 重写:实现类implements不同接口时,接口中存在相同签名的方法(名称、参数、类型完全一致),则实现类必须重写该方法,明确方法定义。
- static修饰的静态方法,属于类的静态方法。但它不能被子类继承,只能用interface接口名称调用。
二、Lambda表达式
Lambda 表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。
使用Lambda 表达式可以使代码变的更加简洁紧凑。
语法格式:(parameters)-> expression 或 (parameters)->{ statements;}
三、函数式接口 Functional Interface
只有一个抽象方法的接口(可以定义多个非抽象方法)。可以使用@FunctionalInterface接口定义,强化语义规范。
作用:基于函数式接口,可以使用Lambda表达式进行实现,实现函数式编程。
示例1:排序
List<String> list=Arrays.asList("ab","hdhdh","a","cd","java");
//Lambda表达式实现Comparator接口
list.sort((o1,o2)->{
if(o1.length()==o2.length()) {
return o1.compareTo(o2);
}
return o1.length()-o2.length();
});
System.out.println(list);
示例2:迭代
public class Demo01 {
public static void main(String[] args) {
List<String> list=Arrays.asList("ab","hdhdh","a","cd","java");
//使用Lambda迭代遍历集合
list.forEach((s)->{
System.out.println(s);
});
}
}
3.1 内置函数式接口 (Built-in Functional Interfaces)
在 Java 8 中专门有一个包放函数式接口java.util.function,该包下的所有接口都有 @FunctionalInterface 注解,提供函数式编程方式。
3.1.1 Predicate接口
Predicate接口是只有一个参数的返回布尔类型值的断言型接口。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与and,或or,非negate)。
public class Demo02 {
public static void main(String[] args) {
List<String> list=Arrays.asList("ab#","hdh$h","a%","cd","java");
//判断长度不等于5
Predicate<String> predicate1=(s)->{
return s.length()!=5;
};
//判断是否全为字母
Predicate<String> predicate2=(s)->{
for(int i=0;i<s.length();i++) {
if(!Character.isLetter(s.charAt(i))) {
return false;
}
}
return true;
};
//逻辑与(and方法与关系型运算符"&&"相似,两边都成立才返回true)
Predicate<String> predicate3=predicate1.and(predicate2);
//逻辑或(or方法与关系型运算符"||"相似,两边只要有一个成立就返回true)
Predicate<String> predicate4=predicate1.or(predicate2);
//逻辑非(与关系运算符"!"相似,对判断进行取反)
Predicate<String> predicate5=predicate4.negate();
list.forEach((s)->{
System.out.println(s+"是否符合条件:"+predicate5.test(s));
});
}
}
3.1.2 Function
Function 接口接受一个参数并生成结果。默认方法可用于将多个函数链接在一起(compose, andThen)。
public class Demo03 {
public static void main(String[] args) {
//Function接口
List<String> list=Arrays.asList("ab#","hdh$h","a%","cd","java");
// list.stream()//切换成stream流
// .map((s)->{ //map映射操作
// //return s.toUpperCase();
// return s.length();
// }).forEach((s)->{
// System.out.println(s);
// });
//转成大写
Function<String, String> fun1=(s)->{
return s.toUpperCase();
};
//添加尖括号
Function<String, String> fun2=(s)->{
return String.format("<%s>", s);
};
//组合
Function<String, String> fun3=fun1.andThen(fun2);
Function<String, String> fun4=fun1.compose(fun2);
list.stream().map(fun3).forEach((s)->{
System.out.println(s);
});
}
}
3.1.3 Comparator
比较器接口,用于比较指定元素值的大小。Java8版本中,添加了多个新的default方法,用于比较器合并、反转等操作。
//Comparator接口
public class Demo04 {
public static void main(String[] args) {
List<String> list=Arrays.asList("ab#","hdhhhh","a%","cd","java");
//按内容比较
Comparator<String> comp1=(x,y)->{
return x.compareTo(y);
};
//按长度比较
Comparator<String> comp2=(x,y)->{
return x.length()-y.length();
};
//先比较内容,再比较长度
Comparator<String> comp3=comp1.thenComparing(comp2);
//按内容降序(反转条件)
Comparator<String> comp4=comp1.reversed();
//按照指定Comparator,进行排序
list.sort(comp4);
System.out.println(list);
}
}
四、Stream流
java.util.Stream 表示能应用在一组元素上一次执行的操作序列。
Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以连续完成多个操作。
4.1 创建Stream
Stream 的创建需要指定一个数据源。
List<String> list=Arrays.asList("稻香","夜曲","东风破","青花瓷");
Stream<String> stream = list.stream();
4.2 常用方法
4.2.1 Filter过滤
过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作。所以过滤后的结果,可以继续进行其它Stream操作(例如forEach,forEach需要一个函数来对过滤后的元素依次执行。forEach是一个最终操作)。
//数组
String[] array= {"稻香","夜曲","东风破","青花瓷","青花瓷","听妈妈的话","夜曲","稻香","稻香"};
Stream<String> arrayStream=Arrays.stream(array);
//先过滤再统计歌曲名称长度为3的数量
long count=arrayStream.filter((music)->{
return music.length()==3;
}).count();
System.out.println(count);
4.2.2 Sorted排序
排序是一个中间操作,返回的是排序好后的Stream。(不影响原数据)
List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
// 排序并遍历
strings.stream()
.sorted()
.forEach(System.out::println);
4.2.3 Map映射
映射是一个中间操作,会将元素根据指定的 Function 接口来依次将元素转成另外的对象。
List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
// 转换字符串为大写,降序后,输出
strings.stream()
.map((item)->{return item.toUpperCase();})
.sorted((s1,s2)->{return s2.compareTo(s1);})
.forEach(System.out::println);
4.2.4 Match匹配
Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配整个Stream。所有的匹配操作都是最终操作 ,并返回一个 boolean 类型的值。
List<String> list=Arrays.asList("稻香","夜曲","东风破","青花瓷");
//是否有任意元素匹配
boolean isContains1=list.stream().anyMatch((music)->{
return music.length()==2;
});
System.out.println(isContains1);
//是否所有元素匹配
boolean isContains2=list.stream().allMatch((music)->{
return music.length()==2;
});
System.out.println(isContains2);
//没有元素匹配
boolean isContains3=list.stream().noneMatch((music)->{
return music.length()==1;
});
System.out.println(isContains3);
4.2.5 Count计数
计数是一个最终操作,返回Stream中元素的个数,返回值类型是 long。
List<String> strings = Arrays.asList("abc", "deft", "gkh", "abc");
// 统计“a”开头的元素个数
long count = strings.stream().filter((s)->s.startsWith("a")).count();
System.out.println(count);
4.2.6 Collect收集
收集是一个最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map)或字符串。
将Stream中的元素,收集至新集合:
- Collectors.toList()
- Collectors.toSet()
- Collectors.toMap()
String[] array= {"稻香","夜曲","东风破","青花瓷","青花瓷","听妈妈的话","夜曲","稻香","稻香"};
Stream<String> arrayStream=Arrays.stream(array);
//去重并收集,将结果收集至List集合,默认为ArrayList
List<String> musicList=arrayStream.distinct()
.collect(Collectors.toList());
System.out.println(musicList);
// 将结果收集至Set集合,默认为HashSet
Set<String> musicSet=Arrays.stream(array).collect(Collectors.toSet());
System.out.println(musicSet);
//distinct去重后,stream中的元素收集成一个LinkedList集合(有序,需要去重)
LinkedList<String> musicLinkedList=Arrays.stream(array)
.distinct()
.collect(Collectors.toCollection(LinkedList::new));
System.out.println(musicLinkedList);
//将stream中的元素收集成一个LinkedHashSet集合(值唯一,有序)
LinkedHashSet<String> musicLinkedHashSet=Arrays.stream(array)
.collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println(musicLinkedHashSet);
//将stream流中的元素收集为一个map集合,默认为HashMap
Map<String,Integer> musicMap1=Arrays.stream(array).distinct()
.collect(Collectors.toMap(
(music)->{return music;},
(music)->{return music.length();}));
System.out.println(musicMap1);
Map<String,Integer> musicMap2=Arrays.stream(array).distinct()
.collect(Collectors.toMap(
music->music,
music->music.length()));
System.out.println(musicMap2);
将Stream中的元素,映射后,收集至新集合:
- Collectors.mapping()
List<String> strList=Arrays.asList("12","23","34","45","56","67");
//收集元素的同时进行mapping映射操作
//将字符串集合中的每个字符串,映射转换为Integer,并将每个数乘10
List<Integer> intList=strList.stream().collect(Collectors
.mapping(
s->Integer.parseInt(s)*10,
Collectors.toList()));
System.out.println(intList);
将Stream中的元素,分组后,收集至Map集合:
- Collectors.groupingBy()
List<String> list=Arrays.asList("曹操","刘备","曹植","张飞","夏侯惇","曹丕","刘能","夏侯渊");
//分组
Map<Character, List<String>> resultMap=list
.stream()
.collect(Collectors
.groupingBy(name->name.charAt(0)));
System.out.println(resultMap);
将Stream中的元素,按照判断规则,统计分区后,收集至Map集合:
- Collectors.partitioningBy()
List<String> list=Arrays.asList("曹操","刘备","曹植","张飞","夏侯惇","曹丕","刘能","夏侯渊");
//分区
Map<Boolean,List<String>> resultPart=list
.stream()
.collect(Collectors.partitioningBy(name->name.length()==2));
System.out.println(resultPart);
4.2.7 Statistics 统计
统计是一个最终操作,返回Stream中元素的各类统计信息,返回值类型是 XXXConsumer。
List<Integer> list=Arrays.asList(2,6,8,10);
Stream<Integer> stream= list.stream();
IntStream intStream=stream.mapToInt(x->x);
IntSummaryStatistics statistics= intStream.summaryStatistics();
System.out.println("最大值:"+statistics.getMax());
System.out.println("最小值:"+statistics.getMin());
System.out.println("平均值:"+statistics.getAverage());
System.out.println("累加和:"+statistics.getSum());
4.2.8 Parallel Streams 并行流
Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。
int max=1000000;
List<String> values=new ArrayList<String>(max);
for(int i=0;i<max;i++) {
UUID uuid=UUID.randomUUID();
values.add(uuid.toString());
}
long start=System.currentTimeMillis();
//串行流
//long count=values.stream().sorted().count();
//并行流
long count=values.parallelStream().sorted().count();
long end=System.currentTimeMillis();
System.out.println(end-start);
注意:
1、一个 Stream 只能操作一次,操作完就关闭了,继续使用这个 Stream 会报错。
2、Stream 不保存数据,不改变数据源。
五、日期时间
5.1 格式化
//yyyy-MM-dd
LocalDate date=LocalDate.now();
System.out.println(String.format("当前日期:%s", date));
//HH:mm:ss
LocalTime time=LocalTime.now().withNano(0);
System.out.println(String.format("当前时间:%s", time));
LocalDateTime dateTime=LocalDateTime.now();
System.out.println(String.format("日期时间:%s", dateTime));
//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));
5.2 字符串转日期格式
//类型转换
//字符串=》LocalDate
String strDate="2023-08-17";
date=LocalDate.parse(strDate);
System.out.println(String.format("指定日期:%s", date));
//整数值-》LocalDate
date=LocalDate.of(2023, 8, 15);
System.out.println(String.format("指定日期:%s", date));
LocalTime time1 = LocalTime.of(12, 12, 22);
LocalTime time2 = LocalTime.parse("12:12:22");
System.out.println(time1);
System.out.println(time2);
LocalDateTime dateTime1 = LocalDateTime.of(2023, 1, 26, 12, 12, 22);
LocalDateTime dateTime2 = LocalDateTime.parse("2023-01-26T12:12:22");
System.out.println(dateTime1);
System.out.println(dateTime2);
5.3 日期计算
LocalDate now=LocalDate.now();
System.out.println(now.plus(10,ChronoUnit.DAYS));
System.out.println(now.plus(-10,ChronoUnit.DAYS));
LocalDate date1=LocalDate.parse("2000-08-18");
LocalDate date2=LocalDate.parse("2021-07-20");
Period result=Period.between(date1, date2);
System.out.printf("间隔%d年,间隔%d月,间隔%d天",result.getYears(),result.getMonths(),result.getDays());
long days=date1.toEpochDay()-date2.toEpochDay();
System.out.println("间隔:"+days+"天");
5.4 获取指定日期
LocalDate today=LocalDate.now();
LocalDate firstDayOfMonth=today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("当月第一天:"+firstDayOfMonth);
System.out.println("当月最后一天:"+today.with(TemporalAdjusters.lastDayOfMonth()));
System.out.println("下个月第一天:"+today.with(TemporalAdjusters.lastDayOfMonth()).plusDays(1));
System.out.println("当月最后一个星期一:"+today.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY)));