Java8实战学习笔记(一)——Java8新改

一、引言

(一)、Java8改进思想

1. Stream API

(流处理)支持许多处理数据的并行操作,其思路类似于数据库查询语言:用更高级的方式表达想要的东西,而由“实现”(Streams库)来选择最佳低级执行机制。  “流水线

好处:可以避免用synchronized编写代码,这一代码不仅容易出错,而且在多核CPU上执行所需的成本也比你想象的要高。

引入Streams可看作以下两项思想产生的直接原因。

  • 对于集合使用处理。

2. 向方法传递代码的技巧

    方法引用、Lambda   --->  使用行为参数化把代码传递给方法

Collections.sort(inventory, new Comparator<Apple>() {
    public int compare(Apple a1, Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
    }
});
改进为 --->
inventory.sort(comparing(Apple::getWeight));
(1)、方法引用(::)

   eg:筛选一个目录中的所有隐藏文件。

File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
    public boolean accept(File file) {
        return file.isHidden();
    }
});
改进为 --->
File[] hiddenFiles = new File(".").listFiles(File::isHidden);

eg:Car类是不同方法引用的例子,区分四种类型的方法引用。

public static class Car {
    public static Car create( final Supplier< Car > supplier ) {
        return supplier.get();
    }              
    // 碰撞
    public static void collide( final Car car ) {
        System.out.println( "Collided " + car.toString() );
    }
    // 跟随
    public void follow( final Car another ) {
        System.out.println( "Following the " + another.toString() );
    }
    // 维修
    public void repair() {   
        System.out.println( "Repaired " + this.toString() );
    }
}
  • 第一种方法引用的类型是构造器引用,语法是Class::new,或者更一般的形式:Class<T>::new。注意:这个构造器没有参数。
    final Car car = Car.create( Car::new );
    final List< Car > cars = Arrays.asList( car );
  • 第二种方法引用的类型是静态方法引用,语法是Class::static_method。注意:这个方法接受一个Car类型的参数。
    cars.forEach( Car::collide );
  • 第三种方法引用的类型是某个类的成员方法的引用,语法是Class::method,注意,这个方法没有定义入参。
    cars.forEach( Car::repair );
  • 第四种方法引用的类型是某个实例对象的成员方法的引用,语法是instance::method。注意:这个方法接受一个Car类型的参数。
    final Car police = Car.create( Car::new );
    cars.forEach( police::follow );
(2)、Lambda —— 匿名函数(::)

将函数(方法)作为值

  • 最简单的Lambda表达式可由 逗号分隔的参数列表 、 ->符号 和 语句块 组成,复杂的再加上{}。可以引用类成员和局部变量(会将这些变量隐式得转换成final的); 有返回值,返回值的类型也由编译器推理得出(若Lambda表达式中的语句块只有一行,则可不使用return语句)。

1.Arrays.asList( "a", "b", "d" ).forEach( s -> System.out.println( s ) );
2.Arrays.asList( "a", "b", "d" ).forEach( e -> {
     System.out.print( e );
     System.out.print( e );
 } );
3.(final)String separator = ",";
  Arrays.asList( "a", "b", "d" ).forEach( 
     ( String e ) -> System.out.print( e + separator ) );

4.Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

5.Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
    int result = e1.compareTo( e2 );
    return result;
} );

eg:假设你有一个Apple类,它有一个getColor方法,还有一个变量inventory保存着一个Apples的列表。你可能想要选出所

有的绿苹果,并返回一个列表。

筛选出绿苹果
public static List<Apple> filterGreenApples(List<Apple> inventory){
    List<Apple> result = new ArrayList<>();
    for (Apple apple: inventory){
        if ("green".equals(apple.getColor())) {
            result.add(apple);
        }
    }
    return result;
}
又:选出重的苹果
public static List<Apple> filterHeavyApples(List<Apple> inventory){
    List<Apple> result = new ArrayList<>();
    for (Apple apple: inventory){
        if (apple.getWeight() > 150) {
            result.add(apple);
        }
    }
    return result;
}
改进为 --->
public static boolean isGreenApple(Apple apple) {
    return "green".equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
    return apple.getWeight() > 150;
}
public interface Predicate<T>{
    boolean test(T t);
}
static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple: inventory){
        if (p.test(apple)) {
            result.add(apple);
        }
    }
    return result;
}

filterApples(inventory, Apple::isGreenApple);
filterApples(inventory, Apple::isHeavyApple);
  •  什么是谓词(Predicate)?前 面 的 代 码 传 递 了 方 法 Apple::isGreenApple ( 它 接 受 参 数 Apple 并 返 回 一 个

boolean)给filterApples,后者则希望接受一个Predicate<Apple>参数。谓词接受一个参数值,并返回true或false。

  • 从传递方法到 Lambda:匿名函数Lambda 简化代码
filterApples(inventory, (Apple a) -> "green".equals(a.getColor()) );
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );    
filterApples(inventory, (Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor()) );

3. 接口中的默认方法和静态方法

  • 默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法会被接口的实现类继承或者覆写。
  • 在接口中可以定义静态方法。
  • Java8新增:stream 、parallelStream
List<Apple> heavyApples1 = inventory.stream().filter((Apple a) -> a.getWeight() > 150).collect(toList());
List<Apple> heavyApples2 = inventory.parallelStream().filter((Apple a) -> a.getWeight() > 150).collect(toList());
  • 如何改变已发布的接口而不破坏已有的实现呢?

如今接口可以包含实现类没有提供实现的方法签名。Who来实现它呢?缺失的方法主体随接口提供了(因此就有了默认实现),而不是由实现类提供。

给接口设计者提供了一个扩充接口的方式,而不会破坏现有的代码。Java 8在接口声明

中使用新的default关键字来表示这一点。

eg: 直接调用List的sort方法,用Java 8 List接口中如下所示的默认方法实现的,它会调用Collections.sort静态方法:

default void sort(Comparator<? super E> c) {
    Collections.sort(this, c);
}
List的任何实体类都不需要显式实现sort


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值