Lambda表达式
lambda表达式的使用依赖于函数式接口,函数式接口可以加注解进行语法验证。
@FunctionalInterface
public interface prodict {
int test(Integer i1,Integer i2);
}
函数式接口
四大函数式接口:
Consumer 消费型接口
@FunctionalInterface
public interface Consumer<T> {
void accept(T var1);
}
Supplier 供给型接口
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Function 函数型接口
@FunctionalInterface
public interface Function<T, R> {
R apply(T var1);
}
Predicate 断言型接口
@FunctionalInterface
public interface Predicate<T> {
boolean test(T var1);
}
其他常用函数式接口:
Comparator 比较型接口
@FunctionalInterface
public interface Comparator<T> {
int compare(T var1, T var2);
boolean equals(Object var1);
}
IntBinaryOperator 一元运算接口
@FunctionalInterface
public interface IntBinaryOperator {
int applyAsInt(int left, int right);
}
引用
方法引用
若Lambda表达式中的内容已经实现了,则可以使用方法引用。即Lambda表达式中的内容是直接调用其他方法,且参数及返回值一致时,则可以使用方法引用。
三种语法格式:
对象::实例方法名
Consumer<Integer> consumer=System.out::println;
consumer.accept(100);
类::静态方法名
Supplier<Double> supplier =Math::random;
System.out.println(supplier.get());
类::实例方法名
当Lambda表示中的第一个参数是实例方法的调用者,第二参数是实例方法的参数时,则可以使用类::实例方法名格式的方法引用。
BiPredicate<String,String> biPredicate=String::equals;
System.out.println(biPredicate.test("a","a"));//true
Function<String,String> function1=String::toUpperCase;
System.out.println(function1.apply("abcd"));//ABCD
构造器引用
语法格式:
类::new
Function<char[],String> function2=String::new;
char[] c={'a','b','c','d'};
System.out.println(function2.apply(c));//abcd
构造器引用,调用的构造取决于函数式接口中方法的参数,方法的参数与构造器参数一致,上述代码中调用的是String(char[])
的构造器。
数组引用
语法格式:
类[]::new
//创建一个长度为10的数组
Function<Integer,String[]> function3=String[]::new;
System.out.println(function3.apply(10).length);//10
Stream流
特性
不会存储元素。
不会改变数据源对象,反而会生成一个持有结果新的Stream。
操作是延迟执行的,只会在需要结果时才执行。
分为串行流(Stream)和并行流(parallelStream),并行流基于Fork/Join框架。
操作
创建Stream
可以通过Collection系列集合提供的Stream。
String[] split = "ABCD".split("");
List<String> list = Arrays.asList(split);
Stream<String> stream = list.stream();
stream.forEach(System.out::println);//A B C D
通过Arrays中的静态方法stream()
获取数组流
String[] split = "ABCD".split("");
Stream<String> stream = Arrays.stream(split);
stream.forEach(System.out::println);//A B C D
通过Stream类中的静态方法of()
String[] split = "ABCD".split("");
Stream<String> stream = Stream.of(split);
stream.forEach(System.out::println);//A B C D
创建无限流:
迭代(iterate)
Stream<Integer> stream = Stream.iterate(1, x -> x + 2);
stream.forEach(System.out::println);//1 3 5 7 9 ······
生成(generate)
Stream<Double> stream = Stream.generate(()-> Math.random());
stream.forEach(System.out::println);//0.1457209369035739 0.931357344126618 0.5592815400556223 ·····
中间操作
筛选和切片
filter
filter 接收Lambda,从流中排除元素。
String[] split = "ABCDB".split("");
List<String> list = Arrays.asList(split);
Stream<String> stream = list.stream();
Stream<String> stream1 = stream.filter(str->!str.equals("B"));
stream1.forEach(System.out::println);//A C D
limit
limit 截断流,使元素不超过给定数量。
Stream<Double> stream = Stream.generate(() -> Math.random());
Stream<Double> stream1 = stream.limit(2);
stream1.forEach(System.out::println);//0.7162022930205418 0.399683785365329
skip
skip(n) 跳过元素,返回一个扔掉前n个元素的流,若流中元素不足时,则返回一个空流,与limit互补。
Stream<Integer> stream = Stream.iterate(1,n->n+1);
stream<Integer> stream1 = stream.skip(5).limit(2);
stream1.forEach(System.out::println);//6 7
distinct
distinct 筛选,通过流所生成元素的hashCode()和equals()去除重复元素。
String[] split = "ABCDB".split("");
List<String> list = Arrays.asList(split);
Stream<String> stream = list.stream();
Stream<String> stream1 = stream.distinct();
stream1.forEach(System.out::println);//A B C D
映射
map
map 接收Lambda,将元素转换成其他形式或者提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,映射成一个新的元素。
String[] split = "ABCDB".split("");
List<String> list = Arrays.asList(split);
Stream<String> stream = list.stream();
Stream<String> stream1 = stream.map(str->str+str);
stream1.forEach(System.out::println);//AA BB CC DD BB
flatMap
flatMap 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连成一个流。
List<String> list= Arrays.asList("aaa","bbb","ccc","ddd");
list.stream().flatMap(str->{
String[] split = str.split("");
Stream<String> stream = Arrays.stream(split);
return stream;
}).forEach(System.out::println);//a a a b b b c c c d d d
排序
sorted()
自然排序:Comparable ,使用的该类型值的默认排序方式。
List<String> list= Arrays.asList("ccc","dddd","a","bb");
Stream<String> stream = list.stream();
Stream<String> stream1 = stream.sorted();
stream1.forEach(System.out::println);//a bb ccc dddd
sorted(Comparator com)
定制排序:Comparator
List<String> list = Arrays.asList("ccc", "dddd", "a", "bb");
Stream<String> stream = list.stream();
Stream<String> stream1 = stream.sorted((str1, str2) -> Integer.compare(str2.length(), str1.length()));
stream1.forEach(System.out::println);//dddd ccc bb a
终止操作
查找与匹配
allMatch
allMatch 检查是否匹配所有元素,全匹配了才返回true,否则返回false。
List<String> list = Arrays.asList("ccc","000", "dddd", "a", "bb");
Stream<String> stream = list.stream();
boolean allMatch = stream.allMatch(String::isEmpty);
System.out.println(allMatch);//false
anyMatch
anyMatch 检查是否至少匹配一个元素,只有有一个匹配就返回true,否则false。
noneMatch
noneMatch 检查是否没有匹配所有元素,只有有一个没有匹配则返回true,否则返回false。
findFirst
findFirst 返回第一个元素
findAny
findAny 返回当前流中任意一个
count
count 返回流中元素的总个数
max
max 返回流中最大值
min
min 返回流中最小值
规约
reduce
无起始值:
reduce(IntBinaryOperator op)
IntStream stream = IntStream.rangeClosed(1, 99);
OptionalInt reduce = stream.reduce((x, y) -> x + y);//计算1-99的和
System.out.println(reduce.getAsInt());
有起始值:
reduce(int identity, IntBinaryOperator op)
IntStream stream = IntStream.rangeClosed(1, 99);
int sum = stream.reduce(0, (x, y) -> x + y);//计算1-99的和
System.out.println(sum);
收集
collect
collect 收集,将流转化为其他形式,接收一个collector接口实现,用户给Stream中元素最汇总方法。
collect(Collector<? super T, A, R> collector);
collector收集器工具类:Collectors,Collectors提供了常用的收集器。
- 将流中的数据转成集合类型: toList、toSet、toMap、toCollection
- 将流中的数据(字符串)使用分隔符拼接在一起:joining
- 对流中的数据求最大值maxBy、最小值minBy、求和summingInt、求平均值averagingDouble
- 对流中的数据进行映射处理 mapping
- 对流中的数据分组:groupingBy、partitioningBy
- 对流中的数据累计计算:reducing
拼接成字符串
List<String> list = Arrays.asList("ccc","000", "dddd", "a", "bb");
Stream<String> stream = list.stream();
String collect = stream.collect(Collectors.joining());//组成一个字符串
System.out.println(collect);//ccc000ddddabb
List<String> list = Arrays.asList("ccc","000", "dddd", "a", "bb","bb");
Stream<String> stream = list.stream();
HashSet<String> collect = stream.collect(Collectors.toCollection(HashSet::new));//放进HashSet容器中
collect.forEach(System.out::println);
求平均值
Stream<Integer> stream = Stream.of(1, 2, 3,10,100);
Double collect = stream.collect(Collectors.averagingInt(Integer::intValue));
System.out.println(collect);//23.2
Optional
optional 是一个容器类,代表一个值存在或不存在。可以很好的避免空指针异常。
方法
方法 | 作用 |
---|---|
Optional.of(T t) | 创建一个为Optional实例 |
Optional.empty() | 创建一个空的Optional实例 |
Optional.ofNullable(T t) | 若t不为null,创建Optional实例,否则创建Optional.empty() |
isPresent() | 判断是否包含值,即是否不为空 |
orElse(T t) | 如果对象有值则返回该值,否则返回t |
orElseGet(Supplier s) | 如果对象有值则返回该值,否则返回s获取的值 |
map(Function f) | 如果有值则对其处理并返回,否则返回Optional.empty() |
flatMap(Function mapper) | 与map类似,但是要去返回值为Optional |
接口默认方法和静态方法
默认方法
public interface IMyFun {
default void get(){
System.out.println("接口默认方法");
}
}
类优先原则
当类继承和实现的相同的方法时,优先调用类的方法,忽略接口方法。
当类实现多个接口时,存在相同方法时,必须重写其中一个接口的方法。
静态方法
public interface IMyFun {
default void get(){
System.out.println("接口默认方法");
}
static void getStatic(){
System.out.println("接口静态方法");
}
}
新日期时间
本地时间
LocalDate
LocalTime
LocalDateTime
时间戳
Instant
Instant instant=Instant.now();
System.out.println(instant);//2020-01-06T01:54:13.959Z
Offset
Instant instant=Instant.now();
System.out.println(instant);//2020-01-06T01:54:13.959Z
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));//偏移量
System.out.println(offsetDateTime);//2020-01-06T09:54:13.959+08:00
LocalDateTime localDateTime1 = offsetDateTime.toLocalDateTime();
System.out.println(localDateTime1);//2020-01-06T09:54:13.959
计算间隔
Duration
计算两个时间之间的间隔
Instant instant = Instant.now();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant instant1 = Instant.now();
Duration between = Duration.between(instant, instant1);
System.out.println(between.getSeconds()+"秒");//1秒
Period
计算两个日期之间的间隔
LocalDate localDate = LocalDate.of(2019, 12, 31);
LocalDate localDate1 = LocalDate.now();
Period between1 = Period.between(localDate, localDate1);
System.out.println(between1.getDays()+"天");//6天
时间校正
TemporalAdjuster
时间矫正器的接口
@FunctionalInterface
public interface TemporalAdjuster {
Temporal adjustInto(Temporal temporal);
}
TemporalAdjusters
提供的时间矫正器实现类
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);//2020-01-06T10:28:55.608
TemporalAdjuster temporalAdjuster = TemporalAdjusters.firstDayOfNextYear();//下一年的第一天
LocalDateTime localDateTime1 = localDateTime.with(temporalAdjuster);
System.out.println(localDateTime1);//2021-01-01T10:28:55.608
TemporalAdjuster temporalAdjuster1 = TemporalAdjusters.next(DayOfWeek.SUNDAY);//下一个周日
LocalDateTime localDateTime2 = localDateTime.with(temporalAdjuster1);
System.out.println(localDateTime2);//2021-01-12T10:28:55.608
自定义校正
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);//2020-01-06T10:51:42.496
//下一个工作日
LocalDateTime localDateTime2 = localDateTime.with(temporal -> {
LocalDateTime localDateTime1 = (LocalDateTime) temporal;
DayOfWeek dayOfWeek = localDateTime1.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY))
return localDateTime.plusDays(3);
else if (dayOfWeek.equals(DayOfWeek.SATURDAY))
return localDateTime1.plusDays(2);
else
return localDateTime1.plusDays(1);
});
System.out.println(localDateTime2);//2020-01-07T10:51:42.496
格式化
DateTimeFormatter
用于时间、日期的解析和转换
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String format = LocalDateTime.now().format(formatter);//转换为指定时间格式
System.out.println(format);//2020-01-06 11:11:50
LocalDateTime dateTime = LocalDateTime.parse(format,formatter);//按指定格式解析
System.out.println(dateTime);//2020-01-06T11:11:50
时区处理
ZoneId
时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
zoneIds.forEach(System.out::println);
ZonedDate
ZonedTime
ZonedDateTime
LocalDateTime dateTime = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(dateTime);//2020-01-06T11:27:12.832
ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.of("Asia/Shanghai"));//在上海时区,与UTC相差8小时
System.out.println(zonedDateTime);//2020-01-06T11:27:12.832+08:00[Asia/Shanghai]