Java 8
Java8 (⼜称 JKD1.8) 是 Java 语⾔开发的⼀个主要版本。Oracle公司于2014年3⽉18⽇发布Java8 。
Lambda 表达式
- Lambda表达式是特殊的匿名内部类,语法更简洁。
- Lambda表达式允许把函数作为⼀个⽅法的参数(函数作为⽅法参数传递),将代码像数据⼀样传递。
注意事项:
- 形参列表的数据类型会⾃动推断。
- 如果形参列表为空,只需保留() 。
- 如果形参只有1个,()可以省略,只需要参数的名称即可。
- 如果执⾏语句只有⼀句,且⽆返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执⾏语句也保证只有⼀句。
- Lambda不会⽣成⼀个单独的内部类⽂件。
函数式接口
- 如果⼀个接⼝只有⼀个抽象⽅法,则该接⼝称之为函数式接⼝。
- 函数式接⼝可以使⽤Lambda表达式,Lambda表达式会被匹配到这个抽象⽅法上 。
- @FunctionalInterface 注解检测接⼝是否符合函数式接⼝规范。
常见的函数式接口
| 接⼝ | 参数类型 | 返回类型 | 说明 |
|---|---|---|---|
| Consumer< T > 消费型接⼝ | T | void | void accept(T t);对类型为T的对象应⽤操作 |
| Supplier< T > 供给型接⼝ | ⽆ | T | T get(); 返回类型为T的对象 |
| Function< T,R > 函数型接⼝ | T | R | R apply(T t);对类型为T的对象应⽤操作,并返回类型为R类型的对象。 |
| Predicate< T > 断⾔型接⼝ | T | boolean | boolean test(T t);确定类型为T的对象是否满⾜条件,并返回 boolean类型。 |
public static void main(String[] args) {
// 使用消费型接口
happy(money -> System.out.println("聚餐花了" + money + "块钱"), 1000.0);
// 使用供给型接口 -> 给别人提供需要的东西
int[] nums = getNums(() -> new Random().nextInt(100), 10);
System.out.println(Arrays.toString(nums));
// 使用函数型接口 x -> y
String hello = handler(String::toUpperCase, "hello");
System.out.println(hello);
ArrayList<String> list = new ArrayList<>();
list.add("zhangsan");
list.add("lisi");
list.add("wangwu");
list.add("zhang");
// 使用断言型接口
List<String> zhang = filter(a -> a.startsWith("zhang"), list);
System.out.println(zhang);
}
// 消费型接口
public static void happy(Consumer<Double> consumer, Double money) {
consumer.accept(money);
}
// 供给型接口
public static int[] getNums(Supplier<Integer> supplier, int count) {
int[] nums = new int[count];
for (int i = 0; i < count; i++) {
nums[i] = supplier.get();
}
return nums;
}
// 函数型接口
public static String handler(Function<String, String> function, String s) {
return function.apply(s);
}
// 断言型接口
public static List<String> filter(Predicate<String> predicate, List<String> list) {
ArrayList<String> newArray = new ArrayList<>();
for (String string : list) {
if (predicate.test(string)) {
newArray.add(string);
}
}
return newArray;
}
方法引用
- ⽅法引⽤是Lambda表达式的⼀种简写形式。
- 如果Lambda表达式⽅法体中只是调⽤⼀个特定的已经存在的⽅法,则可以使⽤⽅法引⽤。
常见形式
- 对象::实例⽅法
- 类::静态⽅法
- 类::实例⽅法
- 类::new
Stream
流(Stream)与集合类似,但集合中保存的是数据,⽽Stream中保存对集合或数组数据的操作。
Stream特点
- Stream ⾃⼰不会存储元素。
- Stream 不会改变源对象。相反,他们会返回⼀个持有结果的新Stream。
- Stream 操作是延迟执⾏的,会等到需要结果的时候才执⾏。
使用步骤
创建:
- 新建⼀个流。 中间操作:
- 在⼀个或多个步骤中,将初始Stream转化到另⼀个Stream的中间操作。 终⽌操作:
- 使⽤⼀个终⽌操作来产⽣⼀个结果。该操作会强制之前的延迟操作⽴即执⾏,在此之后,该Stream就不能使⽤了。
创建Stream
- 通过Collection对象的stream()或parallelStream()⽅法。
- 通过Arrays类的stream()⽅法。
- 通过Stream接⼝的of()、iterate()、generate()⽅法。
- 通过IntStream、LongStream、DoubleStream接⼝中的of、range、rangeClosed⽅法。
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("zhangsan");
arrayList.add("wangwu");
arrayList.add("lisi");
arrayList.add("zhang");
Stream<String> stream = arrayList.stream();
stream.filter(t -> t.startsWith("zhang")).forEach(System.out::println);
// Arrays.stream()
System.out.println(Arrays.stream(new int[]{2, 7, 3, 6, 5, 8, 9, 1}).count());
// Stream().of | .iterate() | .generate()
Stream.of(1, 2, 3, 4).filter(t -> t > 2).forEach(System.out::print);
Stream.iterate(0, x -> x + 2).limit(5).forEach(System.out::print);
Stream.generate(() -> new Random().nextInt(100)).limit(10).forEach(System.out::print);
// range()
IntStream.range(0, 20)/*.filter(t -> t > 4 && t < 15 )*/.forEach(System.out::println);
System.out.println("----");
IntStream.rangeClosed(0, 20)/*.filter(t -> t > 4 && t < 15 )*/.forEach(System.out::println);
}
中间操作
常见的中间操作
- filter、limit、skip、distinct、sorted
- map
- parallel
public static void main(String[] args) {
ArrayList<Student> arrayList = new ArrayList<>();
arrayList.add(new Student("john", 18));
arrayList.add(new Student("jack", 19));
arrayList.add(new Student("rose", 18));
arrayList.add(new Student("rose", 18));
// filter 过滤
Stream<Student> stream = arrayList.stream();
stream.filter(s -> s.getAge() <= 18).forEach(System.out::println);
System.out.println("===================limit====================");
// limit 限制
arrayList.stream().limit(2).forEach(System.out::println);
System.out.println("=====================skip==================");
// skip 跳过
arrayList.stream().skip(2).forEach(System.out::println);
System.out.println("====================distinct===================");
// distinct 去重 -> 重写 equals 和 hasCode
arrayList.stream().distinct().forEach(System.out::println);
System.out.println("====================sort===================");
// sort 排序
arrayList.stream().sorted((Comparator.comparingInt(Student::getAge))).forEach(System.out::println);
System.out.println("=====================map==================");
// map 映射
arrayList.stream().map(Student::getAge).forEach(System.out::println);
System.out.println("=====================parallel==================");
// parallel
arrayList.stream().parallel().forEach(System.out::println);
}
- 串⾏流和并⾏流:
- 串⾏流使⽤单线程。
- 并⾏流使⽤多线程,效率更⾼。
终止操作
常见的终止操作
- forEach、min、max、count
- reduce、collect
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
students.add(new Student("john", 18));
students.add(new Student("jack", 19));
students.add(new Student("rose", 18));
students.add(new Student("rose", 18));
System.out.println("=====================min====================");
// Optional 防止空指针异常的类
Optional<Student> min = students.stream().min((Comparator.comparingInt(Student::getAge)));
Student student = min.get();
System.out.println(student);
System.out.println("=====================max====================");
System.out.println(students.stream().max(Comparator.comparingInt(Student::getAge)).get());
System.out.println("=====================reduce====================");
System.out.println(students.stream().map(Student::getAge).reduce(Integer::sum).get());
System.out.println("=====================collect====================");
List<Integer> collect = students.stream().map(Student::getAge).collect(Collectors.toList());
for (Integer i : collect) {
System.out.println(i);
}
}
新时间API
本地化日期时间API
- LocalDate
- LocalTime
- LocalDateTime
LocalDate localDate = LocalDate.now();
System.out.println(localDate);
LocalTime localTime = LocalTime.now();
System.out.println(localTime);
LocalDateTime dateTime = LocalDateTime.now();
System.out.println(dateTime);
System.out.println(dateTime.getYear());
System.out.println(dateTime.getMonth());
System.out.println(dateTime.getHour());
System.out.println(dateTime.getMinute());
System.out.println(dateTime.getSecond());
System.out.println(dateTime.getDayOfYear());
System.out.println(dateTime.getDayOfMonth());
System.out.println(dateTime.getDayOfWeek());
System.out.println(dateTime.minusDays(1));
System.out.println(dateTime.plusDays(1));
Instant
Instant:时间戳
Instant instant = Instant.now();
System.out.println(instant); // 2024-08-09T01:33:53.332525800Z
System.out.println(instant.getEpochSecond()); // 1723167233
System.out.println(instant.toEpochMilli()); // 1723167233332
Instant instant1 = instant.minusMillis(24 * 60 * 60 * 1000);
System.out.println(instant1); // 2024-08-08T01:34:56.871878300Z
Instant instant2 = instant.plusMillis(24 * 60 * 60 * 1000);
System.out.println(instant2); // 2024-08-10T01:35:22.490775Z
Instant now = Instant.now();
Thread.sleep(5000);
Instant now2 = Instant.now();
// 计算时间差 Duration.between()
long millis = Duration.between(now, now2).toMillis();
System.out.println(millis / 1000);
ZoneId
ZoneId:时区
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
for (String zoneId : zoneIds) {
System.out.println(zoneId);
}
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);
Date、Instant、LocalDateTime
Date、Instant、LocalDateTime的转换
Date date = new Date();
System.out.println(date);
// date -> Instant
Instant instant = date.toInstant();
System.out.println(instant);
// Instant -> LocalDateTime
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(localDateTime);
// LocalDateTime -> Instant
Instant instant1 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println(instant1);
// Instant -> Date
Date from = Date.from(instant1);
System.out.println(from);
DateTimeFormatter
DateTimeFormatter:格式化类
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.now();
String format = dateTime.format(dateTimeFormatter);
System.out.println(format); // 2024-08-09 10:13:48
String date = "2024-08-09 10:13:48";
LocalDateTime time = LocalDateTime.parse(date, dateTimeFormatter);
System.out.println(time);