Java8新特性

Java8在平时工作中被普及的越来越多了,而且Java8也是Java的一次重大版本升级。平时工作中的项目都已经使用了jdk1.8版本,但是关于新特性基本没怎么用到,鉴于平时工作时开始慢慢推行Java8新特性编程,面试中有时候也会涉及到这方面的问题。在此做一个总结,希望自己能有所提高也能帮助别人。

一、Lambda表达式

先看一个lambda表达式的简单例子

//老版本
List<String> fruits = Arrays.asList("apple", "banana", "orange", "watermelon");
for (String fruit : fruits) {
    System.out.print(fruit + "!");
}

//Java8新特性
System.out.println();
fruits.forEach(e -> System.out.print(e + "!"));

可以看出lambda表达式的语法类似:

元素 ->  表达式

二、函数式接口(Functional Interface)

Java使用了很多函数式接口来隐式转换lambda表达式,可以看一下上面的源码:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

进入Consumer里面查看源码,其实Cosumer代表了接受一个输入参数并且无返回的操作

@FunctionalInterface
public interface Consumer<T> {

    /**
     * 对参数做指定操作
     * @param t the input argument
     */
    void accept(T t);
}

接口的@FunctionalInterface注解,表明该接口为为函数式接口。

函数式接口就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

大部分函数式接口我们平时使用时并不用管,Java已经基本实现了大部分。

以下是一个函数式接口的例子(Java8之前一般使用匿名类来实现):

@FunctionalInterface
public interface FruitService {

    void printFruitName(String fruitName);

}

public class FruitTest {

    public static void main(String[] args) {
        FruitService fruitService = fruit -> System.out.println(fruit + "!");
        fruitService.printFruitName("apple");
    }

}

Java8新增加的包涵了大部分函数式接口的接口为java.util.function

三、方法引用

方法引用通过方法的名字来指向一个方法。方法引用可以使语言的结构更紧凑简洁,减少冗余代码。方法引用使用一对冒号 :: 来表示。

下面的实例定义了几种方法做实例:

public class Computer {

    public Computer() {
        System.out.println("Create a computer!");
    }

    public static String askComputer(){
        System.out.println("Where is my computer?");
        return "Where?";
    }

    public void powerOn(Computer computer) {
        System.out.println(computer.toString() + "+++++++开机");
    }

    public static void downKeyBoard(Computer computer){
        System.out.println(computer.toString() + "++++++++敲敲键盘");
    }

    public void powerOff(){
        System.out.println("+++++++关机");
    }
    
}
  • **构造器引用:**它的语法是Class::new,或者更一般的Class< T >::new
Supplier<Computer> computerSupplier = Computer::new;
Computer computer = computerSupplier.get();
  • 静态方法引用: 它的语法是Class::static_method
Supplier<String> askComputer = Computer::askComputer;
System.out.println(askComputer.get());
  • 特定类的任意对象的方法引用: 它的语法是Class::method
computers.forEach(Computer::powerOff);
  • 特定对象的方法引用: 它的语法是instance::method
List<Computer> computers = Arrays.asList(computer);
computers.forEach(computer::powerOn);

测试类如下:

public static void main(String[] args) {
    Supplier<String> askComputer = Computer::askComputer;
    System.out.println(askComputer.get());

    Supplier<Computer> computerSupplier = Computer::new;
    Computer computer = computerSupplier.get();
    System.out.println("计算机名:" + computer.toString());

    List<Computer> computers = Arrays.asList(computer);
    computers.forEach(computer::powerOn);


    computers.forEach(Computer::downKeyBoard);

    computers.forEach(Computer::powerOff);
}

执行结果:
在这里插入图片描述

四、默认方法

Java8新增了接口的默认方法,即接口可以有实现的方法,而且不需要类去实现其方法。

看一下下面的例子就明白了。

public interface Computer {

    default void selfIntroduce(){
        System.out.println("我是一台计算机");
    }

}

public interface KeyBoard {

    default void selfIntroduce(){
        System.out.println("我是一个键盘");
    }

}

public class Laptop implements Computer,KeyBoard{

    @Override
    public void selfIntroduce() {
        Computer.super.selfIntroduce();
        KeyBoard.super.selfIntroduce();
        System.out.println("我是一台笔记本电脑");
    }
}

public class Test {

    public static void main(String[] args) {
        Computer laptop = new Laptop();
        laptop.selfIntroduce();
    }

}

运行结果如下:
在这里插入图片描述

五、Stream

Java8一个重要的特性就是流Stream,可以让我们以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

5.1 什么是流

流(Stream)是一个来自数据源的元素队列并支持聚合操作。

先看一个实例:

public static void main(String[] args) {
    List<String> strings = Arrays.asList("1", "2", "3", "4", "5", "6");
    List<String> list = strings.stream().map(i -> i + "0").collect(Collectors.toList());
    System.out.println(list.toString());
}

结果如下:
在这里插入图片描述
可以看到stream流的使用还是很简洁的。

主要的语法格式为:获取数据源转换为元素流,元素流在管道中经过中间操作处理,最终由最终操作得到前面处理的结果

5.2 生成流的方法

  • stream() – 为集合创建串行流
  • parallelStream() – 为集合创建并行流

刚刚的例子用的就是stream方法生成了流,从而对数据源进行操作

5.3 流的中间操作

map: 用于映射每个元素到对应的结果,如开始的例子

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> integerList = nums.stream().map(x -> x*x).collect(Collectors.toList());
System.out.println(integerList);

filter: 通过设置条件,将符合条件的元素过滤出来

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> collect = nums.stream().filter(num -> (num % 2 == 0)).collect(Collectors.toList());
System.out.println(collect.toString()); //[2, 4, 6]

limit: 用于获取指定数量的流

List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> collect1 = nums.stream().limit(3).collect(Collectors.toList());
System.out.println(collect1.toString()); //[1, 2, 3]

distinct: 提出重复元素

List<Integer> nums = Arrays.asList(1, 2, 3, 2, 3, 1);
List<Integer> integerList = nums.stream().map(x -> x*x).distinct().collect(Collectors.toList());
System.out.println(integerList);//[1, 4, 9]

sorted: 对流进行排序

List<Integer> nums = Arrays.asList(1, 2, 3, 2, 3, 1);
List<Integer> integerList = nums.stream().sorted().collect(Collectors.toList());
System.out.println(integerList);//[1, 1, 2, 2, 3, 3]

5.4 流的终结操作

5.4.1 收集操作

collection(Collection c): Collectors类实现了很多归约操作,如上面的例子经常用过ollect(Collectors.toList())

5.4.2 查找操作

  • allMatch(Predicate p) 返回匹配的元素
  • findFirst() 返回第一个元素
  • count() 反馈元素总数
  • forEach(Consumer c) 这个比较常用

操作有很多,具体还是用的时候百度下参考

六、结论

Java8增加了很多新特性,虽然大部分编程时还是使用以前的编程习惯。但是有的公司可能已经在开始推荐Java8新特性习惯的开发,尤其是使用stream流方面。
因此,学习新的特性,为以后做好准备还是可以的。

参考资料:菜鸟教程 https://www.runoob.com/java/java8-new-features.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值