Java8 新特性一篇文章给你讲透

Java8 新特性一篇文章给你讲透

目录

Java8简介

什么是Java8

Java8是Java语言的一个重要版本,于2014年3月发布。它引入了许多革命性的新特性,特别是函数式编程的支持,使得Java语言更加现代化和强大。

主要特性概览

核心特性:
  - Lambda表达式: 支持函数式编程
  - Stream API: 强大的集合处理能力
  - 新的日期时间API: 替代旧的Date和Calendar
  - 接口默认方法: 接口可以包含实现方法
  - Optional类: 优雅处理空值
  - 方法引用: 简化Lambda表达式
  - 新的Nashorn JavaScript引擎
  - 重复注解支持

与老版本的区别

1. 编程范式变化

Java7及以前:
  - 面向对象编程为主
  - 命令式编程风格
  - 代码相对冗长
  - 集合操作需要循环

Java8:
  - 支持函数式编程
  - 声明式编程风格
  - 代码更简洁优雅
  - Stream API简化集合操作

2. 语法差异对比

// Java7: 传统循环
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> upperNames = new ArrayList<>();
for (String name : names) {
    if (name.length() > 3) {
        upperNames.add(name.toUpperCase());
    }
}

// Java8: Stream API
List<String> upperNames = names.stream()
    .filter(name -> name.length() > 3)
    .map(String::toUpperCase)
    .collect(Collectors.toList());

3. 性能提升

性能改进:
  - 并行流支持多核处理
  - 新的垃圾收集器G1
  - 字符串去重优化
  - 更好的JIT编译器

Lambda表达式

基本语法

// 基本语法: (parameters) -> expression
// 或 (parameters) -> { statements; }

// 示例1: 无参数
Runnable runnable = () -> System.out.println("Hello Lambda");

// 示例2: 单参数
Consumer<String> consumer = (str) -> System.out.println(str);
// 简化写法
Consumer<String> consumer2 = str -> System.out.println(str);

// 示例3: 多参数
BinaryOperator<Integer> add = (a, b) -> a + b;

// 示例4: 多行语句
BinaryOperator<Integer> max = (a, b) -> {
    if (a > b) return a;
    else return b;
};

常见用法

// 集合遍历
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Hello " + name));

// 线程创建
new Thread(() -> {
    System.out.println("Running in thread");
}).start();

// 事件处理
button.addActionListener(e -> System.out.println("Button clicked"));

// 比较器
List<Person> people = Arrays.asList(
    new Person("Alice", 25),
    new Person("Bob", 30)
);
people.sort((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

函数式接口

内置函数式接口

// 1. Predicate<T> - 断言接口
Predicate<String> isLongerThan5 = str -> str.length() > 5;
boolean result = isLongerThan5.test("Hello World"); // true

// 2. Function<T, R> - 函数接口
Function<String, Integer> getLength = String::length;
Integer length = getLength.apply("Hello"); // 5

// 3. Consumer<T> - 消费者接口
Consumer<String> printer = System.out::println;
printer.accept("Hello Consumer");

// 4. Supplier<T> - 供应者接口
Supplier<Double> randomSupplier = Math::random;
Double random = randomSupplier.get();

// 5. BiFunction<T, U, R> - 双参数函数接口
BiFunction<String, String, String> concat = String::concat;
String result = concat.apply("Hello ", "World"); // "Hello World"

自定义函数式接口

@FunctionalInterface
interface MathOperation {
    int operate(int a, int b);
  
    // 可以有默认方法
    default int multiply(int a, int b) {
        return a * b;
    }
}

// 使用自定义函数式接口
MathOperation add = (a, b) -> a + b;
MathOperation subtract = (a, b) -> a - b;

System.out.println(add.operate(10, 5));      // 15
System.out.println(subtract.operate(10, 5)); // 5
System.out.println(add.multiply(10, 5));     // 50

方法引用

方法引用类型

// 1. 静态方法引用
Function<String, Integer> parseInt = Integer::parseInt;
Integer number = parseInt.apply("123");

// 2. 实例方法引用
Function<String, String> toUpperCase = String::toUpperCase;
String upper = toUpperCase.apply("hello");

// 3. 对象方法引用
String prefix = "Hello ";
Function<String, String> addPrefix = prefix::concat;
String result = addPrefix.apply("World"); // "Hello World"

// 4. 构造方法引用
Supplier<ArrayList<String>> listSupplier = ArrayList::new;
ArrayList<String> list = listSupplier.get();

// 5. 数组构造方法引用
Function<Integer, String[]> arraySupplier = String[]::new;
String[] array = arraySupplier.apply(5);

实际应用示例

// 排序
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort(String::compareToIgnoreCase);

// 映射
List<String> upperNames = names.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// 过滤
List<String> longNames = names.stream()
    .filter(name -> name.length() > 4)
    .collect(Collectors.toList());

Stream流

Stream基础概念

Stream特点:
  - 不存储数据,只是数据的视图
  - 不会修改源数据
  - 惰性求值,只有终端操作才会执行
  - 可以并行处理
  - 只能遍历一次

创建Stream

// 1. 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream();

// 2. 从数组创建
String[] array = {"a", "b", "c"};
Stream<String> stream2 = Arrays.stream(array);

// 3. 从值创建
Stream<String> stream3 = Stream.of("a", "b", "c");

// 4. 从函数创建
Stream<Integer> stream4 = Stream.iterate(0, n -> n + 2).limit(10);

// 5. 从生成器创建
Stream<Double> stream5 = Stream.generate(Math::random).limit(5);

// 6. 并行流
Stream<String> parallelStream = list.parallelStream();

中间操作

List<Person> people = Arrays.asList(
    new Person("Alice", 25, "Engineer"),
    new Person("Bob", 30, "Manager"),
    new Person("Charlie", 35, "Engineer"),
    new Person("David", 28, "Developer")
);

// 1. filter - 过滤
List<Person> engineers = people.stream()
    .filter(p -> "Engineer".equals(p.getJob()))
    .collect(Collectors.toList());

// 2. map - 映射
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

// 3. flatMap - 扁平化映射
List<String> allSkills = people.stream()
    .flatMap(p -> p.getSkills().stream())
    .collect(Collectors.toList());

// 4. distinct - 去重
List<String> uniqueJobs = people.stream()
    .map(Person::getJob)
    .distinct()
    .collect(Collectors.toList());

// 5. sorted - 排序
List<Person> sortedByAge = people.stream()
    .sorted(Comparator.comparing(Person::getAge))
    .collect(Collectors.toList());

// 6. limit - 限制数量
List<Person> firstTwo = people.stream()
    .limit(2)
    .collect(Collectors.toList());

// 7. skip - 跳过元素
List<Person> skipFirst = people.stream()
    .skip(1)
    .collect(Collectors.toList());

// 8. peek - 查看元素(调试用)
List<Person> debugged = people.stream()
    .peek(p -> System.out.println("Processing: " + p.getName()))
    .collect(Collectors.toList());

终端操作

// 1. collect - 收集到集合
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

// 2. forEach - 遍历
people.stream().forEach(p -> System.out.println(p.getName()));

// 3. count - 计数
long count = people.stream().count();

// 4. anyMatch - 是否存在匹配
boolean hasEngineer = people.stream()
    .anyMatch(p -> "Engineer".equals(p.getJob()));

// 5. allMatch - 是否全部匹配
boolean allAdults = people.stream()
    .allMatch(p -> p.getAge() >= 18);

// 6. noneMatch - 是否没有匹配
boolean noMinors = people.stream()
    .noneMatch(p -> p.getAge() < 18);

// 7. findFirst - 找到第一个
Optional<Person> first = people.stream()
    .filter(p -> p.getAge() > 25)
    .findFirst();

// 8. findAny - 找到任意一个(并行流中很有用)
Optional<Person> any = people.stream()
    .filter(p -> p.getAge() > 25)
    .findAny();

// 9. reduce - 归约
Optional<Integer> totalAge = people.stream()
    .map(Person::getAge)
    .reduce(Integer::sum);

// 10. min/max - 最小/最大值
Optional<Person> youngest = people.stream()
    .min(Comparator.comparing(Person::getAge));

Optional<Person> oldest = people.stream()
    .max(Comparator.comparing(Person::getAge));

收集器Collectors

// 1. 收集到List
List<String> names = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());

// 2. 收集到Set
Set<String> uniqueNames = people.stream()
    .map(Person::getName)
    .collect(Collectors.toSet());

// 3. 收集到Map
Map<String, Person> nameToPerson = people.stream()
    .collect(Collectors.toMap(
        Person::getName,
        Function.identity()
    ));

// 4. 收集到特定集合
LinkedList<String> linkedList = people.stream()
    .map(Person::getName)
    .collect(Collectors.toCollection(LinkedList::new));

// 5. 连接字符串
String allNames = people.stream()
    .map(Person::getName)
    .collect(Collectors.joining(", "));

// 6. 分组
Map<String, List<Person>> groupedByJob = people.stream()
    .collect(Collectors.groupingBy(Person::getJob));

// 7. 分区
Map<Boolean, List<Person>> partitionedByAge = people.stream()
    .collect(Collectors.partitioningBy(p -> p.getAge() > 30));

// 8. 统计信息
IntSummaryStatistics ageStats = people.stream()
    .mapToInt(Person::getAge)
    .summaryStatistics();

// 9. 自定义收集器
List<String> customCollected = people.stream()
    .map(Person::getName)
    .collect(Collectors.collectingAndThen(
        Collectors.toList(),
        list -> {
            Collections.reverse(list);
            return list;
        }
    ));

并行流处理

// 并行流示例
List<Person> people = Arrays.asList(/* 大量数据 */);

// 并行处理
List<String> names = people.parallelStream()
    .filter(p -> p.getAge() > 25)
    .map(Person::getName)
    .collect(Collectors.toList());

// 并行流注意事项
// 1. 确保操作是无状态的
// 2. 避免修改共享状态
// 3. 某些操作在并行流中可能更慢(如findFirst)

// 性能测试
long start = System.currentTimeMillis();
List<String> sequential = people.stream()
    .map(Person::getName)
    .collect(Collectors.toList());
long sequentialTime = System.currentTimeMillis() - start;

start = System.currentTimeMillis();
List<String> parallel = people.parallelStream()
    .map(Person::getName)
    .collect(Collectors.toList());
long parallelTime = System.currentTimeMillis() - start;

System.out.println("Sequential: " + sequentialTime + "ms");
System.out.println("Parallel: " + parallelTime + "ms");

Optional类

基本用法

// 1. 创建Optional
Optional<String> optional1 = Optional.of("Hello");
Optional<String> optional2 = Optional.ofNullable(null);
Optional<String> optional3 = Optional.empty();

// 2. 判断是否存在
if (optional1.isPresent()) {
    System.out.println(optional1.get());
}

// 3. 安全获取值
String value = optional1.orElse("Default");
String value2 = optional1.orElseGet(() -> "Generated Default");
String value3 = optional1.orElseThrow(() -> new RuntimeException("Value not found"));

// 4. 链式操作
Optional<String> result = optional1
    .filter(s -> s.length() > 3)
    .map(String::toUpperCase);

// 5. 实际应用
public String getUserName(User user) {
    return Optional.ofNullable(user)
        .map(User::getName)
        .orElse("Unknown");
}

实际应用示例

// 传统写法
public String getStreetName(User user) {
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            return address.getStreet();
        }
    }
    return "Unknown Street";
}

// 使用Optional
public String getStreetName(User user) {
    return Optional.ofNullable(user)
        .map(User::getAddress)
        .map(Address::getStreet)
        .orElse("Unknown Street");
}

// 集合操作
List<User> users = Arrays.asList(/* 用户列表 */);
List<String> streetNames = users.stream()
    .map(User::getAddress)
    .filter(Objects::nonNull)
    .map(Address::getStreet)
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

// 使用Optional优化
List<String> streetNames2 = users.stream()
    .map(user -> Optional.ofNullable(user)
        .map(User::getAddress)
        .map(Address::getStreet)
        .orElse(null))
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

新的日期时间API

核心类

// 1. LocalDate - 日期
LocalDate today = LocalDate.now();
LocalDate specificDate = LocalDate.of(2024, 1, 1);
LocalDate parsedDate = LocalDate.parse("2024-01-01");

// 2. LocalTime - 时间
LocalTime now = LocalTime.now();
LocalTime specificTime = LocalTime.of(14, 30, 0);
LocalTime parsedTime = LocalTime.parse("14:30:00");

// 3. LocalDateTime - 日期时间
LocalDateTime now = LocalDateTime.now();
LocalDateTime specificDateTime = LocalDateTime.of(2024, 1, 1, 14, 30, 0);

// 4. ZonedDateTime - 带时区的日期时间
ZonedDateTime zonedNow = ZonedDateTime.now();
ZoneId tokyoZone = ZoneId.of("Asia/Tokyo");
ZonedDateTime tokyoTime = ZonedDateTime.now(tokyoZone);

// 5. Duration - 时间段
Duration duration = Duration.between(startTime, endTime);
long hours = duration.toHours();

// 6. Period - 日期间隔
Period period = Period.between(startDate, endDate);
int years = period.getYears();

实际应用

// 日期计算
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plusWeeks(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate nextYear = today.plusYears(1);

// 日期比较
boolean isAfter = today.isAfter(LocalDate.of(2023, 12, 31));
boolean isBefore = today.isBefore(LocalDate.of(2025, 1, 1));

// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = LocalDateTime.now().format(formatter);

// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-01-01 12:00:00", formatter);

// 时区转换
ZonedDateTime utc = ZonedDateTime.now(ZoneOffset.UTC);
ZonedDateTime local = utc.withZoneSameInstant(ZoneId.systemDefault());

接口默认方法

基本概念

interface Vehicle {
    // 默认方法
    default void start() {
        System.out.println("Vehicle starting...");
    }
  
    // 抽象方法
    void stop();
  
    // 静态方法
    static void info() {
        System.out.println("This is a vehicle interface");
    }
}

class Car implements Vehicle {
    @Override
    public void stop() {
        System.out.println("Car stopping...");
    }
  
    // 可以选择重写默认方法
    @Override
    public void start() {
        System.out.println("Car starting...");
    }
}

实际应用

// 集合接口的默认方法
List<String> list = Arrays.asList("a", "b", "c");

// forEach是默认方法
list.forEach(System.out::println);

// sort是默认方法
list.sort(String::compareTo);

// 自定义接口
interface DataProcessor<T> {
    T process(T data);
  
    default List<T> processBatch(List<T> dataList) {
        return dataList.stream()
            .map(this::process)
            .collect(Collectors.toList());
    }
  
    default void validate(T data) {
        if (data == null) {
            throw new IllegalArgumentException("Data cannot be null");
        }
    }
}

实际应用场景

1. 数据处理

// 用户数据处理
List<User> users = getUserList();

// 过滤、转换、收集
List<String> activeUserEmails = users.stream()
    .filter(User::isActive)
    .map(User::getEmail)
    .filter(email -> email != null && email.contains("@"))
    .collect(Collectors.toList());

// 分组统计
Map<String, Long> usersByRole = users.stream()
    .collect(Collectors.groupingBy(
        User::getRole,
        Collectors.counting()
    ));

// 年龄统计
IntSummaryStatistics ageStats = users.stream()
    .mapToInt(User::getAge)
    .summaryStatistics();

2. 文件处理

// 读取文件并处理
try (Stream<String> lines = Files.lines(Paths.get("data.txt"))) {
    List<String> longLines = lines
        .filter(line -> line.length() > 100)
        .map(String::toUpperCase)
        .collect(Collectors.toList());
}

// 目录遍历
try (Stream<Path> paths = Files.walk(Paths.get("."))) {
    List<Path> javaFiles = paths
        .filter(path -> path.toString().endsWith(".java"))
        .collect(Collectors.toList());
}

3. 数据库查询结果处理

// 假设从数据库查询到用户列表
List<User> users = userRepository.findAll();

// 复杂查询逻辑
Map<String, List<User>> usersByDepartment = users.stream()
    .filter(user -> user.getStatus().equals("ACTIVE"))
    .collect(Collectors.groupingBy(User::getDepartment));

// 统计信息
Map<String, DoubleSummaryStatistics> salaryStats = users.stream()
    .collect(Collectors.groupingBy(
        User::getDepartment,
        Collectors.summarizingDouble(User::getSalary)
    ));

4. 配置处理

// 配置文件处理
Properties props = new Properties();
// ... 加载配置

// 使用Stream处理配置
Map<String, String> config = props.entrySet().stream()
    .collect(Collectors.toMap(
        entry -> entry.getKey().toString(),
        entry -> entry.getValue().toString()
    ));

// 过滤特定配置
List<String> databaseConfigs = config.entrySet().stream()
    .filter(entry -> entry.getKey().startsWith("db."))
    .map(Map.Entry::getValue)
    .collect(Collectors.toList());

5. 异步处理

// 并行处理大量数据
List<String> urls = Arrays.asList(/* URL列表 */);

List<String> results = urls.parallelStream()
    .map(url -> {
        try {
            return fetchUrl(url);
        } catch (Exception e) {
            return "Error: " + e.getMessage();
        }
    })
    .collect(Collectors.toList());

总结

主要优势

Java8优势:
  - 代码更简洁优雅
  - 支持函数式编程
  - 性能提升(并行流)
  - 更好的空值处理
  - 现代化的日期时间API
  - 接口的默认方法

使用建议

最佳实践:
  - 优先使用Stream API处理集合
  - 合理使用Lambda表达式简化代码
  - 注意并行流的适用场景
  - 使用Optional处理空值
  - 充分利用新的日期时间API
  - 合理使用接口默认方法

学习路径

学习顺序:
  1. Lambda表达式基础
  2. 函数式接口
  3. Stream API基础操作
  4. 收集器和高级操作
  5. Optional类使用
  6. 新的日期时间API
  7. 接口默认方法
  8. 实际项目应用

Java8的新特性让Java语言更加现代化和强大,掌握这些特性可以显著提升代码质量和开发效率。建议在实际项目中逐步应用这些特性,积累经验。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值