java jdk1.8新特性

本文深入探讨Java 8中的新特性,包括接口默认方法、函数式编程、lambda表达式、方法引用、构造函数引用、Stream流操作等,通过实例演示如何使用这些新特性简化代码,提高开发效率。

1. 接口默认方法 default关键字.

    在我们的认知中,以前java中的接口都是抽象方法, jdk1.8中增加了具体实现的默认方法,如下:

//函数式接口
@FunctionalInterface
public interface Mouse {
    public String say(String talk);
    
    //接口的默认方法实现
    default String eat() {
        return "eat something";
    }
}

2. 函数式编程: 接口中默认一种抽象方法, 并用注解@FunctionalInterface注解标注, 这样的接口我们就可以用lambda表达式调用了. 增加这个注解以后, 编译器会自动识别接口中的方法是否唯一, 如果有多个参数就会报错, 提示你要写一个抽象方法.

    代码如上

3. lambda表达式

    lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在lambda 内部修改定义在域外的局部变量,否则会编译错误。

    jdk1.8中增加了lambda表达式, 这种写法更加简洁了代码, 一行代码即可搞定,  lambda表达式引入 -> 符号, 符号左面是接口方法中的默认参数, 空参数 则用()即可,多参数 可以用(String x, String y ...), ()中的参数也可以缩略简写成 (x,y ...), 以前接口创建对象时需要重写方法, 写法如下

    public void lambdaTest() {
        Runnable rb = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world ");
            }
        };
        rb.run();
    }

    用lambda表达式后的写法

@Test
    public void lambdaTest1() {
        Runnable rb = () -> System.out.println("hello world");
        rb.run();
    }

 

    第一种 lambda表达式的写法,无参数

    Thread th = new Thread( () -> System.out.println(System.currentTimeMillis()));

    th.start();

    第二种 1个参数的写法

Stream.iterate(0, x -> x+1).limit(100).forEach(System.out::println);

     第三种

   /**
     * lambda表达式 接口和default接口方法用法
     */
    @Test
    public void mouseTest() {
        Mouse mouse = (x) -> x.toUpperCase();
        System.out.println(mouse.say("wangjc say what fuck"));
        System.out.println(mouse.eat());

        Runnable rnb = () -> {
            int count = 0;
            while (true) {
                count++;
                if (count > 100) {
                    break;
                }
                System.out.println("now : " + System.currentTimeMillis());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread th = new Thread(rnb);
        th.start();
    }

4. 方法和构造函数的引用

    首先是构造方法的引用, 写法为 类名::new , 这样会让jdk直接找到默认的 构造函数, 如果没有默认构造函数的话是不可以使用的. 例如

    Supplier<StringBuffer> sb = StringBuffer::new;
    StringBuffer stringBuffer = sb.get();

  然后是方法引用,  类名::方法名

    Stream<Double> generate = Stream.generate(() -> Math.random());
    generate.limit(5).forEach(System.out::println);

  最后是对象引用, 对象名称::方法名

Supplier<StringBuffer> sb = StringBuffer::new;
StringBuffer stringBuffer = sb.get();

Stream<Double> generate = Stream.generate(() -> Math.random());
    generate.limit(5).forEach(stringBuffer::append );

5. Stream 流, jdk 8 中 新增的stream流, Steam API极大得简化了集合操作.

     下列代码是stream的四种获取方式

        List<String> strList = new ArrayList<>();
        Stream<String> stream = strList.stream();

        // 2. 通过Arrays中的静态方法stream()获取数组流
        Employee[] emps = new Employee[10];
        Stream<Employee> stream1 = Arrays.stream(emps);

        // 3. 通过Stream类中的静态方法of()
        Stream<String> stream3 = Stream.of("hello", "wangjc", "world");

        // 4.生成
        Stream<Double> generate = Stream.generate(() -> Math.random());

下面是具体的stream的使用demo

    @Test
    public void streamTest1() {
        Stream<Employee> stream = list.stream();
        Supplier<StringBuffer> sb = StringBuffer::new;
        StringBuffer stringBuffer = sb.get();
        stream.filter(p -> p.getAge() >= 20)
            .sorted((emp1, emp2) -> {
                if (emp1.getAge() > emp2.getAge()) {
                    return 1;
                } else {
                    return 2;
                }
            })

            //limit(5) 是只去流中的5条数据 生成新的流返回, forEach()是开始循环处理
            .limit(5).forEach(stringBuffer::append);
        System.out.println(stringBuffer.toString());
    }

 

class Employee {
    private String userName;
    
    private String userId;
    
    private int age;
    
    public Employee() {
        
    }

    public Employee(String userName, String userId, int age) {
        this.userId = userId;
        this.userName = userName;
        this.age = age;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "username:" + this.userName + "|userid:" + this.userId + "|age:" + this.getAge() + "; hashCode:"
                + this.hashCode();
    }
}

在学习下一个例子之前,还需要记住一些steams的知识点。Steam之上的操作可分为中间操作和晚期操作。

中间操作会返回一个新的steam——执行一个中间操作(例如filter)并不会执行实际的过滤操作,而是创建一个新的steam,并将原steam中符合条件的元素放入新创建的steam。

晚期操作(例如forEach或者sum),会遍历steam并得出结果或者附带结果;在执行晚期操作之后,steam处理线已经处理完毕,就不能使用了。在几乎所有情况下,晚期操作都是立刻对steam进行遍历。

steam的另一个价值是创造性地支持并行处理(parallel processing)。

最后,正如之前所说,Steam API不仅可以作用于Java集合,传统的IO操作(从文件或者网络一行一行得读取数据)可以受益于steam处理,这里有一个小例子:

   final Path path = new File( filename ).toPath();

   try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {

   lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println );

   }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值