Java 8:不可不知的新特性与实用技巧

函数式接口与Lambda

定义:函数式接口是只有一个抽象方法的接口。通过 @FunctionalInterface 注解可以限制接口只能有一个抽象方法。

Lambda 表达式让 Java 支持了函数式编程风格,使得代码更加简洁,并大大简化了对接口的实现。我们一起来看看它支持那些地方使用。

目的: 函数式接口的设计目的是为了能够将其作为 Lambda 表达式的目标类型,从而实现函数式编程的风格。

以下有几个函数式接口和Lambda表达式应用的例子。

Predicate< T >

Predicate 接口表示一个接受单个参数并返回 boolean 值的断言,用于条件判断。

  • 方法: boolean test(T t)
  • 常用场景: 过滤数据、条件判断等。
Predicate<Integer> isEven = x -> x % 2 == 0;
System.out.println(isEven.test(4));  // 输出: true
System.out.println(isEven.test(5));  // 输出: false
Consumer< T >

Consumer 接口表示一个接受单个输入参数并进行某些操作,但不返回结果的操作。

  • 方法: void accept(T t)
  • 常用场景: 用于执行某个操作,如打印、存储、操作数据。
Consumer<Integer> consumer = age -> System.out.println(age);
consumer.accept(5); //输出:5
Supplier< T >

Supplier 接口表示一个无参的提供者,返回特定类型的结果。

  • 方法: T get()
  • 常用场景: 延迟计算、创建新对象等。
Supplier<Integer> supplier = () -> new Random().nextInt();
System.out.println(supplier.get());
Function<T, R>

Function 接口表示一个接受一个输入参数并返回结果的函数。

  • 方法: R apply(T t)
  • 常用场景: 用于转换、映射操作。
Function<String, Integer> stringLength = (s) -> s.length();
System.out.println(stringLength.apply("Hello"));  // 输出: 5
总结
  • Predicate<T> 用于条件判断。
  • Consumer<T> 用于消费数据,不返回结果。
  • Supplier<T> 用于提供数据。
  • Function<T, R> 用于输入输出转换。

Stream API

定义:Stream API 用于处理集合数据,支持链式操作,能够更方便地进行过滤、排序、映射等操作。

创建 Stream
  • Stream.of(T... values): 创建一个包含给定元素的流。
  • Collection.stream():通过一个集合创建一个流。
Stream<Integer> integerStream = Stream.of(1, 2, 3);
integerStream.forEach(System.out::println);

List<Integer> integerList = Arrays.asList(1, 2, 3);
integerList.stream().forEach(System.out::println);
中间操作
  • filter(Predicate<? super T> predicate): 过滤出符合条件的元素。
List<Integer> integerList = Arrays.asList(1, 2, 3);
integerList.stream()
        .filter( x -> x % 2 == 0 ); //只剩能整除2的数
  • map(Function<? super T, ? extends R> mapper): 将每个元素映射为另一个对象。
List<String> list = Arrays.asList("A", "B", "C");
list.stream()
    .map(String::toLowerCase)
    .forEach(System.out::println);  // 输出: a b c
  • sorted(): 对流中的元素进行排序。
java复制代码List<String> list = Arrays.asList("B", "A", "C");
list.stream()
    .sorted()
    .forEach(System.out::println);  // 输出: A B C
终止操作

这些操作会产生一个结果或副作用,并关闭流。

  • forEach(Consumer<? super T> action): 对每个元素执行操作。
List<String> list = Arrays.asList("A", "B", "C");
list.stream()
    .forEach(System.out::println);  // 输出: A B C
  • collect(Collector<? super T, A, R> collector): 将流的元素收集到集合中。
List<String> list = Arrays.asList("A", "B", "C");
List<String> result = list.stream()
    .collect(Collectors.toList());
System.out.println(result);  // 输出: [A, B, C]
  • count(): 返回流中元素的数量。
List<String> list = Arrays.asList("A", "B", "C");
long count = list.stream().count();
System.out.println(count);  // 输出: 3

日期时间 API

LocalDate:表示没有时间的日期(年、月、日)。

LocalTime:表示没有日期的时间(小时、分钟、秒)。

LocalDateTime:表示日期和时间的组合。

ZonedDateTime:表示包含时区的日期时间。

常用方法
  • 获取当前日期和时间

    LocalDate today = LocalDate.now();
    LocalTime now = LocalTime.now();
    LocalDateTime nowDateTime = LocalDateTime.now();
    ZonedDateTime nowZoned = ZonedDateTime.now();
    
  • 格式化日期时间 使用 DateTimeFormatter 类来格式化和解析日期时间。

    示例:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    LocalDate date = LocalDate.parse("2024-10-28", formatter);
    System.out.println(date);  // 输出: 2024-10-28
    
  • 日期时间的加减

    LocalDate nextWeek = LocalDate.now().plusWeeks(1);
    LocalDate previousMonth = LocalDate.now().minusMonths(1);
    
  • 比较日期和时间

    LocalDate date1 = LocalDate.of(2024, 1, 1);
    LocalDate date2 = LocalDate.of(2024, 10, 28);
    boolean isBefore = date1.isBefore(date2);  // true
    boolean isAfter = date1.isAfter(date2);    // false
    

接口默认方法

定义与语法
  • 默认方法使用default关键字来定义,其语法结构如下:

    public interface MyInterface {
        default void myDefaultMethod() {
            System.out.println("This is a default method");
        }
    }
    
特性
  • 可选实现:实现该接口的类可以选择重写默认方法,也可以直接使用接口提供的默认实现。
  • 多重继承:如果一个类实现了多个接口,且这些接口中都有同名的默认方法,编译器会报错,此时需要在实现类中显式重写该方法以消除歧义。
优点
  • 向后兼容性:可以在接口中添加新方法而不影响已有的实现类,确保向后兼容。
  • 减少代码重复:可以为多个实现类提供通用的功能,减少代码的重复。
  • 灵活性:实现类可以选择重写或使用默认实现,提供了灵活的设计。
使用场景
  • API 设计:当需要为接口添加新功能而不破坏已有实现时,可以使用默认方法。
  • 提供通用功能:在接口中实现一些通用功能,供实现类直接使用。

Optional 类

  • 定义Optional 类用来解决可能出现的 NullPointerException 问题,通过显式的空值检查方式,提供更安全的编程方式。

    Optional<String> name = Optional.ofNullable(null);
    name.ifPresent(System.out::println);
    
  • 作用:避免 null 值引发的异常,增强代码的健壮性和可读性。

并行 (Parallel) Stream

  • 定义parallelStream 可以并行化处理流操作,提高处理大数据集合时的性能。

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    numbers.parallelStream().forEach(System.out::println);
    
  • 作用:充分利用多核 CPU 资源,在并发环境下实现数据流的高效处理。

Metaspace

  • 定义:JDK 8 用 Metaspace 取代了永久代 (PermGen),使类元数据存储在本地内存而非堆中。
  • 作用:避免 PermGen 容量固定的缺陷,提升内存管理的灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值