Java 8 新增内容介绍

本文深入探讨Java8的重要新特性,包括Lambda表达式、函数式编程、日期和时间库的改进,以及Stream API的使用。文章通过实例展示了如何利用这些新特性简化代码,提高编程效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大纲

  1. Lambda 表达式
  2. FP(函数式编程)
  3. 日期和时间库
  4. 杂项

Lambda 表达式

Lambda 表达式说明
  1. Lambda 表达式是一个带有参数的代码块。
  2. Lambda 表达式是一段可以传递的代码。
  3. Lambda 表达式可以被转换为函数式接口。
  4. Lambda 表达式可以在闭包作用域中有效的访问final变量。
Java Lambda 示例

定义一个lambda

Predicate<String> notNull1 = (s) -> {
    return Objects.nonNull(s);
};

Predicate<String> notNull2= s -> Objects.nonNull(s);

Method Reference(方法引用)

Predicate<String> notNull3= Objects::nonNull;

直接传递lambda表达式

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("new thread run !");
    }
}).start();

new Thread(()-> System.out.println("new thread run !")).start();

函数式接口指的是拥有@FunctionalInterface注解的接口。

package java.lang;

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

变量作用域

int outer = 0;

@Test
public void testVar() throws Exception {
    int local = 0;//隐式为final
    int old=outer;
    Runnable run = () -> {
        System.out.println(local);//可以调用
        System.out.println(outer);//可以调用
        //local++; 编译错误,无法改变local的值
        outer++;//可以更改
    };
    run.run();
    Assert.assertEquals(old + 1, outer); //通过
}

反向排序

List<Integer> list = Arrays.asList(10, 20, 1, 22, 33);
Collections.sort(list, (o1, o2) -> Integer.compare(o2, o1));

延迟执行

logger.info("x: "+x+", y: "+y+", student: "+student.toString());

logger.info(()->"x: "+x+", y: "+y+", student: "+student.toString());

方法引用用于sql查询

sqlManager.lambdaQuery(Device.class)
	.andEq(Device::getDevNo, devno)
	.andEq(Device::getDeleteFlag, AppConst.YesOrNo.no)
	.single();

FP(函数式编程)

stream 相关API
  • 新增包java.uti.stream
  • java.util.Collectionjava.util.Map等接口增加相关方法。
  • 一些通用的FunctionalInterface(函数式接口)。下面列出只是部分。
    • java.util.function.Supplier
    • java.util.function.Function
    • java.util.function.BiFunction
    • java.util.function.Predicate
    • java.util.function.BiPredicate
    • java.util.function.Consumer
    • java.util.function.BiConsumer
接口默认方法

Java8 在原有的Collection和Map等接口中增加了新的方法。会导致对旧程序不兼容。 比如你写了一个QuickMap,实现了旧的Map接口。Java8在Map接口中增加了新方法,但QuickMap并没有实现它们。

为了向前兼容,Java8在语言层面增肌了新特性,那就是接口默认方法。 针对我们刚才举例的情况,Java8是这么解决的,代码如下:

package java.util;
public interface Map<K,V> {
	
    default V getOrDefault(Object key, V defaultValue) {
        V v;
        return (((v = get(key)) != null) || containsKey(key))
            ? v
            : defaultValue;
    }

    default void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k, v);
        }
    }

    ......
}
Stream 关键方法
  • filter 过滤
  • map 转换
  • flatMap 展开并转换
  • collect 收集stream中的数据
  • reduce 聚合操作
Stream 示例代码

取字符串列表中,不为空的,小写的,每个字符串的开头和末尾两个字符,组成新的列表。

List<String> wordList = Arrays.asList("Hello","", "WOrld", "Lily", "and"," ", "Han");
List<Character> charList = wordList.stream()
        .filter(w -> w != null && w.trim().length() >= 2)
        .map(w -> w.toLowerCase())  // .map(String::toLowerCase);
        .flatMap(w -> Stream.of(w.charAt(0), w.charAt(w.length() - 1)))
        .collect(Collectors.toList());

通过账号列表获取逗号分隔的id列表

List<Account> accountList = ... ;
String ids = accountList.stream()
	.map(Account::getId)
	.collect(Collectors.joining(","));

通过账号列表,获取id到username的映射

Map<String, String> idToName = accountList.stream()
	.collect(Collectors.toMap(Account::getId, Account::getUsername));

账号按部门分组

List<Account> accountList = ... ;
Map<String, List<Account>> depWithAccountList = accountList.stream()
        .filter(a -> a.getDepId() != null)
        .collect(Collectors.groupingBy(Account::getDepId));

计算和

List<Integer> nums = Arrays.asList(1, 3, 4, 6, 2, 3, 1);

Integer sum = nums.stream().reduce(0, (x, y) -> x + y);

Optional<Integer> sum2 = nums.stream().reduce((x, y) -> x + y);

int sum3 = nums.stream().mapToInt(Integer::intValue).sum();

日期和时间库

java.time
  1. java.time.Instant 时间线上的一个时间点.
  2. java.time.Duration 两个时间点之间间隔.
  3. java.time.LocalDateTime日期时间,与时区无关。
  4. java.time.ZonedDateTime日期时间,与时区关联。
示例代码

获取当前毫秒值

Instant.now().toEpochMilli()

打印当前日期时间

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDateTime now = LocalDateTime.now();//instant + offset
System.out.println(dateTimeFormatter.format(now));

ZonedDateTime now1 = ZonedDateTime.now();//instant + zone
System.out.println(dateTimeFormatter.format(now1));

Instant|LocalDateTime|ZonedDateTime 之间转换

LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.now(),
		ZoneId.systemDefault());
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(Instant.now(), 
		ZoneId.systemDefault());

ZonedDateTime zonedDateTimeTmp = LocalDateTime.now().atZone(ZoneId.systemDefault());

Instant instant = zonedDateTimeTmp.toInstant();

与Date的转换

Date from = Date.from(Instant.now());
Instant instant = new Date().toInstant();

杂项

String自带join
String join = String.join(",", "1", "3", "4");
String join1 = String.join(",", Arrays.asList("2", "3", "6"));
String join2 = String.join(",", new String[]{"1", "2", "3"});
System.out.println(join);
System.out.println(join1);
System.out.println(join2);
Optional 可选值
Random r = new Random();
Optional<String> val = Optional.ofNullable(r.nextBoolean() ? null : "1");
//不为空时才处理
val.ifPresent(v -> {
    String line = v + "hello";
    System.out.println(line);
});
//不为空则转换为int,为空则返回-1
Integer number = val.map(Integer::parseInt).orElse(-1);

Optional<Object> empty = Optional.empty();
文件操作 (Java7开始)

按行读取文本文件内容

try(Stream<String> lines= Files.lines(Paths.get("test.txt"))){
    List<String> collect = lines.filter(Texts::hasText)
            .collect(Collectors.toList());
}

遍历目录,包含子目录。深度优先遍历

try (Stream<Path> entries = Files.walk(Paths.get("rootDir"))) {
    //打印文件名
    entries.map(Path::getFileName)
            .peek(System.out::println);
}
java.util.Objects (Java7开始)
  • Objects#equals
  • Objects#deepEquals
  • Objects#hashCode
  • Objects#toString
  • Objects#compare
  • Objects#requireNonNull
  • Objects#isNull
  • Objects#nonNull
  • ......

转载于:https://my.oschina.net/huanger/blog/2986960

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值