【总结篇中】Java8新特性总结

本文详细介绍Java8中的StreamAPI,包括Stream的基本概念、操作步骤、创建方法、中间操作、终止操作等,并提供丰富的示例代码说明如何使用Stream进行数据处理。

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/88826272








四、Stream API

1、Stream概述

Stream API是 Java8中重大的改变,称为“流”。它专门用来处理集合,对集合中的数据进行查找、过滤和映射等操作。

注意:

1)Stream 自己不会存储元素;

2)Stream 不会改变源对象,他们会返回一个持有结果的新Stream;

3)Stream 操作是延迟执行的。这意味着他们会等到结果的时候才执行。

2、Stream的操作步骤

1)创建Stream

通过一个数据源(如:集合、数组),获取一个流

2)中间操作

一个中间操作链,对数据源的数据进行处理

3)终止操作(终端操作)

一个终止操作,执行中间操作链,并产生结果

Stream终止操作流水线

3、创建Stream

1)可以通过 Collection系列集合提供的 stream() 或 parallelStream()(并行流)

List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

2)通过 Arrays中的静态方法 stream()获取数组

Employee[] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);

3)通过 Stream类中的静态方法 of()

Stream<String> stream3 = Stream.of("aa", "bb", "cc");

4)创建无限流

// 迭代 iterate()
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x+2);
stream4.limit(10).forEach(System.out::println);
// 生成 generate()
Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);

4、Stream中间操作

1)筛选与切片

filter(Predicate p)

过滤元素,从流中留下某些元素。

limit(long n)

截断元素,选取前n个元素

skip(long n)

跳过元素,扔掉了前n个元素的流,留下剩下的元素。若流中元素不足n个,则返回一个空流。

distinct()

筛选元素,去除重复元素(通过元素的hashCode()和equals()去除重复)

2)映射

map(Function<T, R> mapper)

将元素转换成其他形式或提取信息。

flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

将流中的每个值都换成另一个流,然后把所有流连接成一个流。

map与flatMap的区别:

map: { {a,a,a}, {b,b,b}, … }

flatMap: {a,a,a,b,b,b,…}

3)排序

sorted()

自然排序(Cmparable)

sorted(Comparator com)

比较器排序(Comparator)

5、Stream终止操作

1)查找与匹配

allMatch(Predicate p)

检查是否匹配所有元素

anyMatch(Predicate p)

检查是否至少匹配一个元素

noneMatch(Predicate p)

检查是否没有匹配所有元素

findFirst()

返回流中第一个元素

findAny()

返回当前流中的任意元素

count()

返回流中元素的总个数

max(Comparator c)

返回流中最大值

min(Comparator c)

返回流中最小值

forEach(Consumer c)

内部迭代,用于遍历,替代了增强for循环

2)归约

reduce(T identity, BinaryOperator bo)

可以将流中元素反复结合起来,得到一个值。返回T

reduce(BinaryOperator bo)

可以将流中元素反复结合起来,得到一个值。返回Optional<T>

3)收集

collect(Collector c)

将流转换为其他形式。对流中的数据进行收集汇总,接收一个 Collector接口的实现Collectors类是专门用来创建收集器的工具类,它里面提供了很多静态方法,可以方便地创建常见收集器实例:

List Collectors.toList()

List收集器

Set Collectors.toSet()

Set收集器

ArrayList Collectors.toCollection(ArrayList::new)

集合收集器,可指定任意集合

Long Collectors.counting()

计数收集器

Integer Collectors.summingInt(i -> i)

求和收集器

Double Collectors.averagingDouble(i -> i)

平均值收集器

IntSummaryStatistics Collectors.summarizingInt(i -> i)

收集流中Integer属性的统计值。

例如:

iss.getAverage();   // 平均值
iss.getCount();     // 总数
iss.getMax();       // 最大值
iss.getMin();       // 最小值
iss.getSum();       // 求和

String Collectors.joining()

连接流中每个元素

Optional Collectors.maxBy(Double::compareTo)

最大值

Optional Collectors.minBy(Double::compareTo)

最小值

Map<K, List<V>> Collectors.groupingBy(Function func[, Collector coll])

分组

Map<Boolean, List<T>> Collectors.partitioningBy(Predicate predicate)

分区

6、应用

备用数据:

List<Employee> emps = Arrays.asList(
    new Employee("张三", 14, 3242.2, Status.ERROR),
    new Employee("李四", 32, 5342.23, Status.OK),
    new Employee("王五", 21, 64523.23, Status.OK),
    new Employee("王五", 21, 64523.23, Status.OK),
    new Employee("王五", 21, 64523.23, Status.OK),
    new Employee("赵六", 83, 541.2, Status.ERROR)
);

1)内部迭代与外部迭代

// 内部迭代:迭代操作由 Stream API 完成 
@Test
public void test1() {
    // 中间操作:不会执行任何操作
    Stream<Employee> stream1 = emps.stream().filter((x) -> {
        System.out.println("Stream API 中间操作");
        return x.getAge() > 30;
    });
    // 终止操作:一次性执行全部内容,即“惰性求值”
    stream1.forEach(System.out::println);
}

// 外部迭代
@Test
public void test2() {
    Iterator<Employee> it = emps.iterator();
    while (it.hasNext()) {
        System.out.println(it.next());
    }
}

2)Stream中间操作之【筛选与切片】

/*
 * filter(Predicate p):过滤元素,从流中留下某些元素。
 * limit(long n):截断元素,选取前n个元素。
 * skip(long n):跳过元素,扔掉了前n个元素的流,留下剩下的元素。
 * distinct():筛选元素,去除重复元素
 */
@Test  
public void test() {
    emps.stream()
        //.filter((e) -> e.getAge() > 20)
          .filter((e) -> {
              System.out.println("短路");
               // 当找到满足条件的2条数据,后面的数据就不再执行了,
               // 相当于短路了,提高了效率  
               return e.getAge() > 20;
          })
          .limit(2)    // 取前两个
          .forEach(System.out::println);    // [李四…] [王五…]
    emps.stream()
          .filter((e) -> e.getAge() > 20)
          .skip(2)    // 除了前两个
          .forEach(System.out::println);    // [王五…] [王五…] [赵六…]
    emps.stream()
          .distinct()   // 去除重复
          .forEach(System.out::println);    // [张三…][李四…][王五…][赵六…]
}

3)Stream中间操作之【映射】

/*
 * map(Function<T, R> mapper):将元素转换成其他形式或提取信息。
 * flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
 *      将流中的每个值都换成另一个流,然后把所有流连接成一个流。
 */
@Test
public void test() {
    List<String> list = Arrays.asList("aaaa", "bbb", "cccc", "ddd");
    list.stream()
        //.map((x) -> x.length() > 3)
        .map((str) -> str.toUpperCase())
        .forEach(System.out::println);
    System.out.println("--------------------");    // [AAAA,BBB,CCCC,DDD]
    emps.stream()
        //.map((e) -> e.getName())
        .map(Employee::getName)
        .forEach(System.out::println);
    System.out.println("---------------------");   // 张三 李四 王五 王五 王五 赵六

   // map: { {a,a,a}, {b,b,b}, ... }
   // flatMap: {a,a,a,b,b,b,...}
   // 原理类似:add(Object obj) 与 addAll(Collection coll)
   //      add: [11, 22, [aa, bb, cc]]
   //      addAll: [11, 22, aa, bb, cc]
    Stream<Stream<Character>> map = list.stream()
        .map(TestLambda7::filterChar);
    map.forEach((sm) -> sm.forEach(System.out::println));

    System.out.println("---------------------");
    Stream<Character> map2 = list.stream()
        .flatMap(TestLambda7::filterChar);
    map2.forEach(System.out::println);
}

public static Stream<Character> filterChar(String str) {
    List<Character> list = new ArrayList<>();
    for (Character ch : str.toCharArray()) {
        list.add(ch);
    }
    return list.stream();   // [a,a,a]
}

4)Stream中间操作之【排序】

/*
 * sorted():自然排序(Cmparable)
 * sorted(Comparator com):比较器排序(Comparator)
 */
@Test
public void test() {
    List<String> list = Arrays.asList("ddd", "bbb", "aa", "eee", "ccc");
    list.stream().sorted().forEach(System.out::println);   // [aa, bbb, ccc, ddd, eee]

    emps.stream()
        .sorted((e1, e2) -> {
            int num = e1.getAge() - e2.getAge();
            return num == 0 ? e1.getName().compareTo(e2.getName()) : num;
        })    // 先按年龄排,年龄相同,再按姓名排
        .forEach(System.out::println);
}

5)Stream终止操作之【查找与匹配】

/*
 * allMatch(Predicate p):检查是否匹配所有元素
 * anyMatch(Predicate p):检查是否至少匹配一个元素
 * noneMatch(Predicate p):检查是否没有匹配所有元素
 * findFirst():返回流中第一个元素
 * findAny():返回当前流中的任意元素
 * count():返回流中元素的总个数
 * max(Comparator c):返回流中最大值
 * min(Comparator c):返回流中最小值
 */
@Test
public void test() {
    boolean bool1 = emps.stream().allMatch((e) -> e.equals(Status.OK));
    System.out.println(bool1);    // false
    boolean bool2 = emps.stream().anyMatch((e) -> e.equals(Status.ERROR));
    System.out.println(bool2);    // false
    boolean bool3 = emps.stream().noneMatch((e) -> e.equals(Status.ERROR));
    System.out.println(bool3);    // true
    Optional<Employee> op = emps.stream().findFirst();
    System.out.println(op.get());  // 张三…
    Optional<Employee> op2 = emps.stream().findAny();
    System.out.println(op2.get());  // 张三…
    long count = emps.stream().count();
    System.out.println(count);   // 6

    Optional<Employee> op3 = emps.stream()
        .max((e1, e2) -> {
            int num = e1.getAge() - e2.getAge();
            return num == 0 ? e1.getName().compareTo(e2.getName()) : num;
        });
    System.out.println(op3.get());   // 赵六

    Optional<Employee> op4 = emps.stream()
        .min((e1, e2) -> {
            int num = e1.getAge() - e2.getAge();
            return num == 0 ? e1.getName().compareTo(e2.getName()) : num;
        });
    System.out.println(op4.get());     // 张三
}

6)Stream终止操作之【归约】

/*
 * reduce(T identity, BinaryOperator bo):可以将流中元素反复结合起来,得到一个值。返回T
 * reduce(BinaryOperator bo):可以将流中元素反复结合起来,得到一个值。返回Optional<T>
 */
@Test
public void test() {
    List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
    Integer sum = list.stream()
        .reduce(0, (t1, t2) -> t1+t2);   // 初值为0,所以相加后的结果不会是空指针异常
  /*
    * 第一次:t1=0,t2=1, 0+1=1
    * 第二次:t1=1,t2=2, 1+2=3
    * 第三次:t1=3,t2=3, 3+3=6
    * ...
    */
    System.out.println(sum);     // 55

    double s = Double.sum(10.203, 24.12);
    System.out.println(s);       // 34.323

    Optional<Integer> op = list.stream().reduce(Integer::sum);
    System.out.println(op.get()); // 没有给定初值,所以可能会出现空指针异常,所以返回Optional对象 		//  55
    Optional<Double> op2 = emps.stream().map(Employee::getSalary).reduce(Double::sum);
    System.out.println(op2.get());    // 202695.32000000004

}

7)Stream终止操作之【收集】

/*
 * collect(Collector c):将流转换为其他形式。
           对流中的数据进行收集汇总,接收一个 Collector接口的实现
 * Collectors类是专门用来创建收集器的工具类,
           它里面提供了很多静态方法,可以方便地创建常见收集器实例
 *
 * List<T> Collectors.toList():List收集器
 * Set<T> Collectors.toSet():Set收集器
 * ArrayList Collectors.toCollection(ArrayList::new):集合收集器(可以指定任意集合)
 */
@Test
public void test1() {
    List<String> list = emps.stream()
        .map(Employee::getName)
        .distinct()
        .collect(Collectors.toList());    // 将流中的数据转换为List集合
    System.out.println(list);    // List:[张三, 李四, 王五, 赵六]
    System.out.println("------------------");

    String[] arr = {"aaa", "bb", "dddd", "cc", "eeeeeeee"};
    List<String> list2 = Arrays.stream(arr)
        .filter((str) -> str.length() > 3)
        .collect(Collectors.toList());
    list2.forEach(System.out::println);    // List:dddd eeeeeeee
    System.out.println("---------------------");

    Set<String> set = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.toSet());
    set.forEach(System.out::println);    // Set:[李四 张三 王五 赵六]
    System.out.println("---------------------");

    ArrayList<String> list3 = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.toCollection(ArrayList::new));
    list3.forEach(System.out::println);    // ArrayList: [张三 李四 王五 王五 王五 赵六]
}

/*
 * Long Collectors.counting():计数收集器
 * Integer Collectors.summingInt(i -> i):求和收集器
 * Double Collectors.averagingDouble(i -> i):平均值收集器
 * Optional Collectors.maxBy(Double::compareTo):最大值
 * Optional Collectors.minBy(Double::compareTo):最小值
 */
@Test
public void test2() {
    // 收集流中元素的总数
    String[] arr = {"aaa", "bb", "dddd", "cc", "eeeeeeee"};
    Long count = Arrays.stream(arr).collect(Collectors.counting());
    System.out.println(count);    // 5
    System.out.println("-----------------------------");

    // 平均值
    Double[] arr2 = {1.0,2.0,3.0,4.0,5.0,6.0};
    Double avg = Arrays.stream(arr2).collect(Collectors.averagingDouble((i) -> i));
    // 注意:数组的类型是引用数据类型,而且在这里不会进行自动封装,元素也必须是对应的数据类型。
    System.out.println(avg);    // 3.5
    System.out.println("-----------------------------");

    emps.stream()
        .collect(Collectors.averagingDouble((e) -> e.getSalary()));

    // 求和
    Double sum = Arrays.stream(arr2).collect(Collectors.summingDouble(i -> i));
    System.out.println(sum);     // 21.0
    System.out.println("-----------------------------");
    // 最大值
    Optional<Double> op = Arrays.stream(arr2).collect(Collectors.maxBy(Double::compareTo));
    System.out.println(op.get());    // 6.0
    // 最小值
    Optional<Double> op2 = Arrays.stream(arr2).collect(Collectors.minBy(Double::compareTo));
    System.out.println(op2.get());    // 1.0
}

/*
 * IntSummaryStatistics Collectors.summarizingInt(i -> i):收集流中Integer属性的统计值。
 *      如:iss.getAverage();  // 平均值
 *          iss.getCount();    // 总数
 *          iss.getMax();      // 最大值
 *          iss.getMin();      // 最小值
 *          iss.getSum();      // 求和
 */
@Test
public void test3() {
    Integer[] arr = {1,2,3,4,5};
    IntSummaryStatistics iss = Arrays.stream(arr).collect(Collectors.summarizingInt(i -> i));
    System.out.println(iss);
    // IntSummaryStatistics{count=5, sum=15, min=1, average=3.000000, max=5}
    System.out.println(iss.getAverage());  // 平均值
    System.out.println(iss.getCount());    // 总数
    System.out.println(iss.getMax());      // 最大值
    System.out.println(iss.getMin());      // 最小值
    System.out.println(iss.getSum());      // 求和
}

/*
 * 合并成字符串
 * String Collectors.joining():连接流中每个元素
 */
@Test
public void test4() {
    String str1 = emps.stream().map(Employee::getName).collect(Collectors.joining());
    System.out.println(str1);    // 张三李四王五王五王五赵六
    String str2 = emps.stream().map(Employee::getName).collect(Collectors.joining(","));
    System.out.println(str2);    // 张三,李四,王五,王五,王五,赵六
    String str3 = emps.stream().map(Employee::getName)
        .collect(Collectors.joining(",", "====前====", "----后----"));
    System.out.println(str3);    // ====前====张三,李四,王五,王五,王五,赵六----后----
}

/*
 * 分组
 * Map<K, List<V>> Collectors.groupingBy(Function func[, Collector coll]):分组
 */
@Test
public void test5() {
    // 按状态分组
    Map<Status, List<Employee>> map = emps.stream()
        .collect(Collectors.groupingBy(Employee::getStatus));
    System.out.println(map);
    // {ERROR=[Employee [name=张三...], ...], OK=[Employee [name=李四...], ...]}

}

// 多级分组
@Test
public void test6() {
    Map<Status, Map<String, List<Employee>>> map = 
        emps.stream().collect(Collectors.groupingBy(
        Employee::getStatus, Collectors.groupingBy((e) -> {
            if (((Employee) e).getAge() < 20) {
                return "少年英雄";
            } else if (((Employee) e).getAge() < 40) {
                return "中年";
            } else {
                return "老当益壮";
            }
        })));

    // {ERROR={老当益壮=[Employee...], 少年英雄=[Employee...]}, OK={中年=[Employee...]}
}

/*
 * 分区
 * Map<Boolean, List<T>> Collectors.partitioningBy(Predicate predicate):分区
 */
@Test
public void test7() {
    Map<Boolean, List<Employee>> map = emps.stream()
        .collect(Collectors.partitioningBy((e) -> e.getStatus().equals(Status.OK)));
    System.out.println(map);
    // {false=[Employee...], true=[Employee...]}
}




五、并行流与串行流

1、并行流概述

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。

Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。

2、Fork/Join 框架

Fork/Join框架是Java 7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

Fork/Join框架

3、Fork/Join 框架与传统线程池的区别

采用 “工作窃取”模式(work-stealing):

当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。

相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上。在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行。这种方式减少了线程的等待时间,提高了性能。

4、应用

public class TestForkJoin {
    // 普通for
    @Test
    public void test2() {
        Instant start = Instant.now();
        long sum = 0l;
        for (long i = 0; i <= 10000000000L; i ++) {
            sum += i;
        }
        System.out.println(sum);
        Instant end = Instant.now();
        System.out.println("耗费时间:" + Duration.between(start, end).toMillis());   // 6149
    }

    // ForkJoin框架
    @Test
    public void test() {
        Instant start = Instant.now();

        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinCalculate(0, 10000000000L);
        Long sum = pool.invoke(task);
        System.out.println(sum);

        Instant end = Instant.now();
        System.out.println("耗费时间:" + Duration.between(start, end).toMillis());   // 4667
    }
    // Java8并行流
    @Test
    public void test3() {
        Instant start = Instant.now();
        long sum = LongStream.range(0, 10000000000L)
            .parallel()
            .reduce(0, Long::sum);
        System.out.println(sum);
        Instant end = Instant.now();
        System.out.println("耗费时间:" + Duration.between(start, end).toMillis());   // 4232
    }
}




六、Optional 类

1、Optional类概述

Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以尽最大努力避免空指针异常。

2、常用方法

Optional.of(T t)

创建一个 Optional实例

Optional.empty()

创建一个空的Optional实例

Optional.ofNullable(T t)

若t不为null,创建Optional实例,否则创建空实例

isPresent()

判断是否包含值

orElse(T t)

如果调用对象包含值,返回该值,否则返回t

orElseGet(Supplier s)

如果调用对象包含值,返回该值,否则返回s获取的值

map(Function f)

如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()

flatMap(Function mapper)

与map类似,要求返回值必须是Optional

3、注意事项

使用Optional容器来包装可能为空的对象,但需要注意创建Optional实例时如果没有对象,则要保证是一个空实例(Optional.empty)。

4、应用

// 女孩类
public class Girl {
    private String name;
    public Girl() { }
    public Girl(String name) { ... }
    get()...&set()...
        toString() ...
}
// 男孩类
public class Boy {
    // Girl这个对象可能为空,所以用Optional包装,但此时没有具体实例,则需要初始化一个空实例
    private Optional<Girl> girl = Optional.empty();
    public Boy() { }
    public Boy(Optional<Girl> girl) { ... }
    get()...&set()...
        toString() ...
}
@Test   // 测试类
public void test() {
    Optional<Boy> op = Optional.ofNullable(new Boy());
    String girlName = getGirlName(op);
    System.out.println(girlName);     // 会输出默认值
}
// 需求:获取一个男孩心中女孩的名字
// 现在的写法
public String getGirlName(Optional<Boy> boy) {
    return boy.orElse(new Boy())   // 如果不包含,则使用默认的
        .getGirl()         // 此时boy肯定不会为空
        .orElse(new Girl("苍老师"))
        .getName();
}
// 以前的写法
public String getGirlName(Boy boy) {
    // return boy.getGirl().getName();   // 这样容易报空指针异常
    // boy与girl都可能为空,所以要用if语句进行判断
    if (boy != null) {
        Girl g = boy.getGirl();
        if (g != null) {
            return g.getName();
        }
    }
    return "苍老师";
}

Java 8Java 17 的版本中引入了大量新特性,极大地提升了 Java 的表达能力、性能以及开发效率。以下是这些版本中主要新特性的总结,适用于学习和技术笔记。 ### 一、Java 8 新特性 Java 8 是一次重大更新,引入了许多现代编程语言的特性,主要包括: - **Lambda 表达式**:允许将函数作为参数传递,简化了集合操作和并发编程。 - **函数式接口**:仅包含一个抽象方法的接口,支持 Lambda 表达式作为函数式编程的基础。 - **方法引用**:通过 `ClassName::methodName` 或 `object::methodName` 的形式直接引用已有方法。 - **默认方法**:接口中可以包含默认实现的方法,使用 `default` 关键字修饰,解决了接口演进问题。 - **静态方法**:接口中也可以定义静态方法,便于工具方法的封装。 - **Stream API**:提供声明式的集合操作方式,支持链式调用,如 `filter`、`map`、`reduce` 等。 - **Optional 类**:用于避免空指针异常,鼓励更安全的代码风格。 - **新的日期时间 API(java.time)**:引入 `LocalDate`、`LocalTime`、`LocalDateTime` 等类,替代旧版 `Date` 和 `Calendar`,具有更好的线程安全性和易用性 [^3]。 ```java // 示例:Stream API 与 Lambda 表达式 List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); List<String> filtered = names.stream() .filter(name -> name.startsWith("A")) .map(String::toUpperCase) .toList(); ``` ### 二、Java 9 新特性 Java 9 引入了模块化系统,并增强了工具链和 API: - **模块系统(JPMS)**:通过 `module-info.java` 定义模块,提升大型系统的可维护性和安全性。 - **JShell(REPL)**:提供交互式命令行,方便快速测试 Java 代码片段。 - **接口私有方法**:允许接口中定义 `private` 方法,用于辅助默认方法实现。 - **HTTP/2 客户端(实验性)**:引入新的 HTTP 客户端 API,支持同步和异步请求 [^6]。 ### 三、Java 10 新特性 Java 10 增加了一些实用特性,提升开发效率: - **局部变量类型推断(var)**:允许使用 `var` 声明局部变量,编译器自动推断类型。 - **GC 改进**:引入并行 Full GC 的 G1 垃圾收集器。 - **统一垃圾回收接口**:为不同垃圾收集器提供统一接口,便于扩展 [^7]。 ```java // 示例:var 类型推断 var list = new ArrayList<String>(); list.add("Hello"); ``` ### 四、Java 11 新特性 Java 11 是一个长期支持版本(LTS),引入了多个增强功能: - **单文件源码执行(jshell-like)**:支持直接运行 `.java` 文件,无需显式编译。 - **HTTP Client API 增强**:支持同步和异步请求,支持 WebSocket。 - **字符串增强方法**:如 `isBlank()`, `lines()`, `repeat(n)` 等。 - **文件读写新方法**:如 `Files.writeString()` 和 `Files.readString()` [^8]。 ```java // 示例:Java 11 单文件执行 // 可以直接运行 java MyClass.java public class MyClass { public static void main(String[] args) { System.out.println("Hello from Java 11"); } } ``` ### 五、Java 12-14 新特性 这几个版本继续引入语言和工具链的小幅改进: - **Switch 表达式(Java 12/13)**:支持返回值和简化语法,使用 `->` 替代 `:`。 - **文本块(Java 13)**:使用 `"""..."""` 定义多行字符串。 - **模式匹配(instanceof 类型匹配)(Java 14)**:简化类型判断与转换 [^9]。 ```java // 示例:switch 表达式 int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; }; ``` ### 六、Java 15-17 新特性 这些版本进一步推进语言现代化和性能优化: - **密封类(Sealed Classes)(Java 15/17)**:限制类或接口的继承关系,增强封装性。 - **移除实验性 AOT/JIT 编译器(Java 16)**。 - **记录类(Records)(Java 16)**:简化不可变数据类的定义。 - **模式匹配增强(Java 16)**:支持 `switch` 中的类型匹配。 - **强封装 JDK 内部 API(Java 16)**:限制访问内部 JDK 类。 - **Vector API(孵化阶段)(Java 16)**:支持 SIMD 指令优化。 - **结构化并发(Structured Concurrency)(Java 19)**:简化多线程编程模型(虽为 Java 19,但影响后续版本设计) [^10]。 ```java // 示例:record 类型 record Point(int x, int y) {} ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小异常

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值