JDK1.8新特性

JDK1.8新特性

本文作为JDK1.8学习过程中的总结;便于自己反复查阅温故知新。

接口中的非抽象方法

JDK1.8之前,接口类只能定义抽象方法。但在JDK1.8之后,接口类可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现。那么这么做有什么好处吗?

  1. 减少了代码量;比如:当一个接口有多个实现类时,提取公共方法到接口中,不用再编写公共类给实现类继承了。
  2. 对既有的类进行功能扩展, 且不必对这些类重新进行设计。 比如, 只需在Collection接口中增加default Stream stream(), 相应的Set和List接口以及它们的子类都包含此的方法, 不必为每个子类都重新copy这个方法。
public interface UserService {
    /**
     * 在jdk1.8之前,接口中只能存在抽象方法
     */
    void fun1();

    /**
     * jdk1.8之后可以存在以static修饰的非抽象方法,实现了该接口的实现类对象都可以调用次方法
     */
    static void fun2() {
        // dosomething
    }

    /**
     * jdk1.8之后可以存在以关键字default修饰的非抽象方法,实现了该接口的实现类对象都可以调用次方法
     */
    default void fun3() {
        // dosomething
    }
}

函数式接口

JDK1.8中引入的lambda表达式、方法引用,都涉及到了方法接口都是为了函数式编程服务

@FunctionalInterface
public interface Converter<F, T> {
    /**
     * 将某个类型的参数转成另一个类型
     * @param t 要转换的对象
     * @return 转换后的结果
     */
    F converter(T t);
}

Lambda表达式

Lambda实质就是将函数式接口自己实现后得到该接口的对象,然后调用该接口的方法。因为在接口中只是申明了方法签名而没有对方法进行实现,所以在实际操作时符合方法签名的前提下可以任意实现。并且实现一次后可反复调用。
观察main方法中的3中写法,可以发现一种比一种简洁易读、易懂,这个就是lambda的好处。

public class FuncationInterfaceDemo {
    public static void main(String[] args) {
        String s = "456";
        // 在jdk1.8之前,使用匿名内部类需要实现该接口
        Converter<Integer, String> converter1 = new Converter<Integer, String>() {
            @Override
            public Integer converter(String s) {
                return Integer.valueOf(s);
            }
        };
        System.out.println(converter1.converter(s));


        // jdk1.8及之后可以通过lambda表达式完成
        Converter<Integer, String> converter2 = (str) -> {
            return Integer.valueOf(str);
        };
        System.out.println(converter2.converter(s));

        // 同时,在jdk1.8之后,如果lambda表达式中的内容是一个现成的方法,那么还可以对它进行简化,也就是方法引用
        Converter<Integer, String> converter3 = Integer::valueOf;
        System.out.println(converter3.converter(s));
    }
}

其他函数接口

public class OtherFunctionInterface {
    public static void main(String[] args) {
        /*
        应用场景:有两个集合需要处理,[1, 2, 3, 5] 找出该集合中的偶数,["a", "ab", "abc", "c"] 找出元素长度是1的
        按照以前的写法会对这两个集合进行遍历,稍微封装一下,将处理的过程封装成两个方法,一个方法判断 element % 2 == 0
        另一个方法判断 element.length == 1
        但是使用了Predicate接口以后,却只要实现一个方法就行了,具体看下面例子
         */


        // Predicate 接口接受一个参数,返回boolean类型,方法具体由自己实现
        Predicate<String> predicate = (s -> s.length() > 1);

        // true
        System.out.println(predicate.test("test"));

        // false
        System.out.println(predicate.negate().test("test"));

        // 并且实现了or、and等一些默认方法以及静态方法,可以配合使用
        Predicate<String> predicate1 = s -> s.length() == 1;

        // false
        System.out.println(predicate1.test("123"));

        // false
        System.out.println(predicate.and(predicate1).test("123"));

        // true
        System.out.println(predicate.or(predicate1).test("123"));


        Integer[] integers = {1, 2, 3, 5};
        String[] strings = {"a", "ab", "abc", "c"};
        Predicate<Integer> filter1 = integer -> integer % 2 == 0;
        Predicate<String> filter2 = s -> s.length() == 1;

        filter(integers, filter1);
        filter(strings, filter2);

    }

    /**
     * 过滤
     * 使用了predicate作为参数,根据具体实现不同,过滤规则也不同
     *
     * @param arrays        要过滤的数据
     * @param predicate 过滤表达式
     * @param <T>       泛型
     */
    private static <T> void filter(T[] arrays, Predicate<T> predicate) {
        for (int i = 0; i < arrays.length; i++) {
            if (predicate.test(arrays[i])) {
                System.out.println(arrays[i]);
            }
        }
    }
}

optional

有效避免非空检验,较少if 判断

public class OptionDemo {
    public static void main(String[] args) {
        User user = new User();

        // 把指定的值封装为Optional对象
        System.out.println(Optional.of(user));
        // 如果指定的值为null,则抛出NullPointerException
//        System.out.println(Optional.of(null));

        // 创建一个空的Optional对象
        System.out.println(Optional.empty());

        // 与of相同,将对象封装成Optional对象
        System.out.println(Optional.ofNullable(user));
        // 与of区别,如果是null将返回一个空的Optional对象
        System.out.println(Optional.ofNullable(null));

        // 如果创建的Optional中有值存在,则返回此值,否则抛出NoSuchElementException
        Optional<User> optional = Optional.of(user);
        System.out.println(optional.get());
        optional = Optional.ofNullable(null);
//        System.out.println(optional.get());

        optional = Optional.ofNullable(null);
        user.username = "test";
        // 如果创建的Optional中有值存在,则返回该值,否则返回一个默认值(入参)
        System.out.println(optional.orElse(new User()));
        System.out.println(optional.orElse(null));

        // 如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值
        System.out.println(optional.orElseGet(() -> new User()));

        // 如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常
//        System.out.println(optional.orElseThrow(() -> new NullPointerException()));

        optional = Optional.of(user);
        user.username = "xu";
        // 如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象
        System.out.println(optional.filter((u -> u.username != null)));

        // 如果创建的Optional中的值存在,对该值执行提供的Function函数调用
        System.out.println(optional.map(u -> u.username.replace("x", "xixixi")));
        // 如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象
        System.out.println(optional.flatMap(u -> Optional.of(new User())));


        optional = Optional.ofNullable(null);
        // 如果创建的Optional中的值存在,返回true,否则返回false
        System.out.println(optional.isPresent());

        optional = Optional.of(user);
        user.username = "x";
        // 如果创建的Optional中的值存在,则执行该方法的调用,否则什么也不做
        optional.ifPresent(s -> System.out.println(s.username));


    }
}

Stream类似于流,单向,不可往复。可以对集合的所有元素进行筛选,过滤,修改等,但是只能对数据遍历一次,如果需要第二次操作,必须继续创建Stream流。
Stream操作分为三个步骤:创建Stream–>中间操作–>最终操作。

public class StreamDemo {
    public static void main(String[] args) {
        //直接使用静态方法,获取指定值的顺序排序流
        Stream<String> stream1 = Stream.of("aa", "bb", "cc");

        String[] strArray = {"a", "b", "c"};
        //使用的Arrays类的stream方法
        Stream<String> stream2 = Arrays.stream(strArray);

        List<String> list = Arrays.asList(strArray);
        //直接使用集合获取流
        Stream<String> stream3 = list.stream();

        // 对数据进行遍历
        stream1.forEach(s -> System.out.println(s));
        // 流只能使用一次,如果要再次使用,只能再建流
        stream1 = Stream.of("aa", "bb", "cc");
        stream1.forEach(System.out::println);

        // 对数据进行过滤
        System.out.println("------------------------------------------------");
        stream1 = Stream.of("aa", "bb", "cc");
        stream1.filter(s -> s.startsWith("a")).forEach(System.out::println);

        // 对数据进行排序
        System.out.println("------------------------------------------------");
        stream1 = Stream.of("cc", "bb", "aa");
        stream1.sorted().forEach(System.out::println);


        // 对每个元素进行操作
        System.out.println("------------------------------------------------");
        stream1 = Stream.of("cc", "bb", "aa");
        stream1.map(s -> s.toUpperCase()).forEach(System.out::println);

        // 统计,放在流操作的最后面,当使用count之后,流消失
        System.out.println("------------------------------------------------");
        stream1 = Stream.of("cc", "bb", "aa");
        System.out.println(stream1.filter(s -> s.startsWith("a")).count());

        System.out.println("------------------------------------------------");
        stream1 = Stream.of("cc", "bb", "aa");
        stream1.reduce((s1, s2) -> s1 + "-" + s2).ifPresent(System.out::println);

        // 即进行串行操作,单线程。时间长
        list.stream();

        // 并行操作,多线程同时进行。需要时间短
        list.parallelStream();

    }
}

理解Lambda表达式 - https://blog.csdn.net/GoGleTech/article/details/79454151

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值