java8新特性Optional正确处理集合长度为0的索引越界问题

java8新特性Optional正确处理集合长度为0的索引越界问题

java8提供的lambda表达式有效的帮助我们解决Null指针的问题,并且提高了代码的阅读性和美观性。

示例

普通的代码编写如下。可以看到if噩梦,代码可读性很差,并且编写的代码量也很多

    public static void testOptional(){
        A a = new A();
        B b = new B();
        C c = new C();

        a.setB(b);
        b.setC(c);

        if(a != null){
            B b1 = a.getB();
            if(b1 != null){
                C c1 = b1.getC();
                if(c1 != null){
                    System.out.println("c1的值:" + c1.getList().toString());
                }
            }
        }
}

使用java8提供的Optional编写。

    public static void testOptional(){
        A a = new A();
        B b = new B();
        C c = new C();

        a.setB(b);
        b.setC(c);

        String s = Optional.ofNullable(a)
                .map(A::getB)
                .map(B::getC)
                .map(C::getList)
                .map(res -> res.get(0))
                .orElse("111");

        System.out.println("s==="+s);
}

Optional提供了2个静态方法。分别是ofNullable和of。如果a等于null,使用ofNullable不会报错,会自动返回一个空的Optional对象。使用of会直接包Null指针

以上代码执行的流程

  • 以上代码是为了从A对象里获得B对象,然后从B对象获取C对象,最后获取C对象的集合元素。map会自动帮我们判断传入对象是否为空,如果为空,直接抛出异常,并且交由orElse捕获。

  • 2 例如上述代码,如果B对象是null,那么在执行(.map(B::getC))的时候,就会直接跳转到orElse输出111

存在的问题 集合长度为0的问题

当C对象中的集合对象不为null,但是长度为0,这是会就会报索引越界的异常。具体原因可以看下map的源码。如下

    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 boolean isPresent() {
        return value != null;
    }

可以看到isPresent()函数中,仅仅只是判断value是否为null,当我们传递进来的集合不为空,但是长度为0的时候,这儿也会默认放行。所以就导致了我们在list.get(0)的时候的索引越界

解决方案

filter进行自定义拦截判断。可以将代码修改为如下

    public static void testOptional(){
        A a = new A();
        B b = new B();
        C c = new C();

        a.setB(b);
        b.setC(c);

        String s = Optional.ofNullable(a)
                .map(A::getB)
                .map(B::getC)
                .map(C::getList)
                .filter(x -> x != null && x.size() != 0)  //自定义判读集合不为空并且长度不为0
                .map(res -> res.get(0))
                .orElse("111");

        System.out.println("s==="+s);
    }
# java 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×