Java8 一些常用语法总结

概述

java8一大特点就是lambda表达式,简化代码,稍微总结一下一些常用的语法。

Optional

优雅的判空,代替繁琐的 xxx!=null 写法简化代码

Optional常用方法:
1、Optional(T value),empty(),of(T value),ofNullable(T value)
  • Optional(T value),即构造函数,它是private权限的,不能由外部调用的。其余三个函数是public权限,供程序员所调用。Optional的本质,就是内部储存了一个真实的值,在构造的时候,就直接判断其值是否为空。
  • of(T value)函数内部调用了构造函数,源码如下:
public static <T> Optional<T> of(T value) {
   return new Optional<>(value);
}
  • empty()的作用就是返回EMPTY对象。源码如下:
public final class Optional<T> {
    // 省略....
    private static final Optional<?> EMPTY = new Optional<>();
    private Optional() {
        this.value = null;
    }
    // 省略...
    public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
}
  • ofNullable(T value),相比较of(T value)的区别就是,当value值为null时,of(T value)会报NullPointerException异常;ofNullable(T value)不会throw Exception,ofNullable(T value)直接返回一个EMPTY对象。(这个比较常用)源码如下:
 public static <T> Optional<T> ofNullable(T value) {
    return value == null ? empty() : of(value);
}
2、orElse(T other),orElseGet(Supplier<? extends T> other) 和 orElseThrow(Supplier<? extends X> exceptionSupplier)

三个函数都是在构造函数传入的value值为null时,进行调用的。

  • orElse 和 orElseGet的用法如下所示,相当于value值为null时,给予一个默认值。用法如下:
@Test
public void test() {
    User user = null;
    user = Optional.ofNullable(user).orElse(createUser());
    user = Optional.ofNullable(user).orElseGet(() -> createUser());
    
}
public User createUser(){
    User user = new User();
    user.setName("zhangsan");
    return user;
}

这两个函数的区别:当user值不为null时,orElse函数依然会执行createUser()方法,而orElseGet函数并不会执行createUser()方法。

  • orElseThrow,就是value值为null时,直接抛一个异常出去,用法如下:
User user = null;
Optional.ofNullable(user).orElseThrow(()->new Exception("用户不存在"));
3、map(Function<? super T, ? extends U> mapper) 和 flatMap(Function<? super T, Optional> mapper)

这两个函数都是做一些值转换的操作的,源码如下:

 public final class Optional<T> {
    // 省略....
     public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
    // 省略...
     public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }
}

这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function<? super T, ? extends U>,而flapMap的入参类型为Function<? super T, Optional<U.>>。用法如下:

public void getCity8(User user) throws Exception {
        // User::getAddress <=> u->u.getAddress()
        String city = Optional.ofNullable(user)
                .map(User::getAddress)
                .map(Address::getCity)
                .orElseThrow(() -> new Exception("map() 取值错误"));

        String city2 = Optional.ofNullable(user)
                .flatMap(u -> Optional.ofNullable(u.getAddress()))
                .flatMap(ad -> Optional.ofNullable(ad.getCity()))
                .orElseThrow(() -> new Exception("flatMap() 取值错误"));

        System.out.println("city: " + city + ", " + city2);
    }
4、isPresent() 和 ifPresent(Consumer<? super T> consumer)

顾名思义,isPresent 是判断 value 值是否为空,而 ifPresent 就是在value值不为空时,做一些操作。源码如下:

public final class Optional<T> {
    //省略....
    public boolean isPresent() {
        return value != null;
    }
    //省略...
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }
}
5、filter(Predicate<? super T> predicate)

filter() 是用来过滤筛选数据的,跟过滤器一个理儿。源码如下:

public final class Optional<T> {
    //省略....
   Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(value) ? this : empty();
}

filter 方法接受一个 Predicate 来对 Optional 中包含的值进行过滤,如果包含的值满足条件,那么还是返回这个 Optional;否则返回 Optional.empty。用法如下:

Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);

以上摘自 https://blog.csdn.net/zjhred/article/details/84976734

Stream

流式编程,常用语集合上,常用方法跟 Optional 的有些方法一样。这里列举一下常用例子。

常用方法使用案例

List<User> users = new ArrayList<User>()
例1: filter() & collect(Collectors.toList()) 过滤数据得到一个新的集合。

List<User> usersList = users.stream()
         .filter(u -> u.getAge() > 3)
         .collect(Collectors.toList());

例2: collect(Collectors.toMap()) 把 list 集合转成 map,这里也可结合 filter() 使用
这里不会覆盖相同key,而是拼接。如果要覆盖,只留一个key即可:(key1, key2) -> key2

Map<Integer, String> stringMap = users.stream()
         .collect(
                  Collectors.toMap(
                           User::getAge, 
                           User::getName, 
                           (key1, key2) -> key1 + "," + key2
                  ));

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
例3: map() 将 List<Integer> 转成 List<String>

 List<String> result1 = integerList.stream()
         .map(value -> String.format("String:%s", value)).collect(toList());
System.out.println("result1: " + JSON.toJSONString(result1));

输出结果:
result1: ["String:1","String:2","String:3","String:4","String:5"]

例4: flatMap() 将每个 Integer 元素都生成一个新的 Stream 并将这些 Stream 连接成一个新的 Stream

List<Integer> result2 = integerList.stream().flatMap(value -> {
            Integer[] is = new Integer[value];
            for (int i = 0; i < value; i++) {
                is[i] = value;
            }
            return Stream.of(is);
        }).collect(toList());
System.out.println("result2: " + JSON.toJSONString(result2));

输出结果:
result2:[1,2,2,3,3,3,4,4,4,4,5,5,5,5,5]

例5: reduce() 求List中所有元素之和
reduce 函数的一个参数为循环的初始值,这里计算累加时初始值为 0,acc 代表已经计算的结果,item 表示循环的每个元素。

Integer sum = integerList.stream().reduce(0, (acc, value) -> acc + value);
System.out.println("sum: " + sum);

输出结果:
sum: 15

例6: 取List中的最大值 和 最小值
min 和 max 函数需要一个 Comparator 对象为参数作为比对依据

Comparator<Integer> comparator = Integer::compareTo;
System.out.println("min: " + integerList.stream().min(comparator).get());
System.out.println("max: " + integerList.stream().max(comparator).get());

输出结果:
min: 1
max: 5

例7 groupingBy 对list进行分组,类似数据库sql的 group by xxx
Product实体类:

public class Product {
    private Long id;
    private Integer num;
    private BigDecimal price;
    private String name;
    private String category;
}

List<Product> prodList = new ArrayList<Product>()
1、按照类目分组

Map<String, List<Product>> prodMap01 = prodList.stream()
        .collect(Collectors.groupingBy(Product::getCategory));
// 统计总数
Map<String, Long> prodMap05 = prodList.stream()
        .collect(Collectors.groupingBy(Product::getCategory, Collectors.counting()));

// 求和
Map<String, Integer> prodMap06 = prodList.stream()
        .collect(Collectors.groupingBy(
                Product::getCategory, 
                Collectors.summingInt(Product::getNum)));

例8 compute() 统计一句英语中每个字母出现的次数

String str = "hello java,  nice to meet you.";
HashMap<Character, Integer> result2 = new HashMap<>(32);
for (int i = 0; i < str.length(); i++) {
    char curChar = str.charAt(i);
    result2.compute(curChar, (k, v) -> v == null ? 1 : v + 1);
}
System.out.println(result2);

输出结果:
{ =6, a=2, c=1, e=4, h=1, i=1, j=1, ,=1, l=2, m=1, .=1, n=1, o=3, t=2, u=1, v=1, y=1}

——————————————————————— End ——————————————————————————————
有不足之处 或者 语法用法有误 的地方还请指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值