java8 笔记 - 常用函数式接口(三)

常用函数式接口

Predicate

Predicate接口的test方法,接收一个参数,返回一个布尔值。

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T var1);
}

举例:

先看个简单的例子:判断字符串长度是否大于5

public class LambdaTest {

    public static void main(String[] args) {

        //Predicate接收一个参数,返回布尔值
        Predicate<String> predict = (String str) -> { return str.length() > 5; };

        System.out.println(predict.test("hello"));

        System.out.println(predict.test("welcome"));

    }
}
输出:
false
true

再看一个例子,有一个Apple集合,现在要筛选出红色的苹果

public class Apple {
    private String category;
    private String color;
    private double weight;

    public Apple(String category, String color, double weight) {
        this.category = category;
        this.color = color;
        this.weight = weight;
    }
    // getter and setter and toString
}
public class LambdaTest {

    public static void main(String[] args) {

        Apple apple1 = new Apple("红星", "Red", 280);
        Apple apple2 = new Apple("黄元帅", "Yello", 470);
        Apple apple3 = new Apple("红将军", "Red", 320);
        Apple apple4 = new Apple("国光", "Green", 300);

        List<Apple> appleList = Arrays.asList(apple1, apple2, apple3, apple4);

        //filter方法接收一个Predicate类型的参数
        appleList.stream().filter(apple -> "Red".equals(apple.getColor()))
                          .forEach(apple -> System.out.println(apple));

    }
}
输出:
Apple{category='红星', color='Red', weight=280.0}
Apple{category='红将军', color='Red', weight=320.0}
  • stream 是Collection的一个方法,将集合转换成流。
  • filter是stream的一个方法表示过滤。
  • forEach是Iterable的方法,迭代处理。

我们先不关注stream、filter、forEach方法,主要关注filter方法的参数,它接收一个Predict类型的参数,Predict,接收一个参数,返回一个布尔值,

apple -> “Red”.equals(apple.getColor()): 一个输入参数,返回布尔值,符合Predict接口定义。如果需要筛选出红色的,重量大于300克的苹果,方法如下:

appleList.stream().filter(apple -> "Red".equals(apple.getColor()) && (300 < apple.getWeight()))
                .forEach(apple -> System.out.println(apple));

 //或者(filter方法返回的还是Stream)              
 appleList.stream().filter(apple -> "Red".equals(apple.getColor()))
                .filter(apple -> 300 < apple.getWeight())
                .forEach(apple -> System.out.println(apple));

Supplier

Supplier 不接收参数,返回一个值。

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

举例:返回一个随机int值:() -> new SecureRandom().nextInt(20) 符合不接收参数,返回一个值的定义

public class LambdaTest {

    public static void main(String[] args) {

        Supplier<Integer> randomInt = () -> new SecureRandom().nextInt(20);

        System.out.println(randomInt.get());
    }
}

BinaryOperator

BinaryOperator 接口继承自BiFunction,接收两个参数,返回一个值,与BiFunction不同的是,它的两个输入参数和返回值都是同一种类型。其实第二节的四则运算的例子用BinaryOperator实现更为方便。

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T, T, T> {
    static default <T> BinaryOperator<T> minBy(Comparator<? super T> var0) {
        Objects.requireNonNull(var0);
        return (var1, var2) -> {
            return var0.compare(var1, var2) <= 0?var1:var2;
        };
    }

    static default <T> BinaryOperator<T> maxBy(Comparator<? super T> var0) {
        Objects.requireNonNull(var0);
        return (var1, var2) -> {
            return var0.compare(var1, var2) >= 0?var1:var2;
        };
    }
}

举例:

public class LambdaTest {

    public static void main(String[] args) {

        Integer num1 = 16, num2 = 2;

        MyCalculator<Integer> calculator = new MyCalculator<>();


        System.out.println(calculator.comput(num1, num2, (n1, n2) -> n1 + n2));

        System.out.println(calculator.comput(num1, num2, (n1, n2) -> n1 - n2));

        System.out.println(calculator.comput(num1, num2, (n1, n2) -> n1 * n2));

        System.out.println(calculator.comput(num1, num2, (n1, n2) -> n1 / n2));

    }
}

class MyCalculator<T> {

    public T comput(T t1, T t2, BinaryOperator<T> binaryOperator) {
        return binaryOperator.apply(t1, t2);
    }
}
输出:
18
14
32
8

我们看到BinaryOperator有两个静态方法minBy,maxBy,这两个静态方法返回一个BinaryOperator结果,这个BinaryOperator的返回值是根据minBy的参数Comparator来决定的。

public class LambdaTest {

    public static void main(String[] args) {

        //返回一个BinaryOperator对象
        BinaryOperator<String> binaryOperator = BinaryOperator.minBy((str1, str2) -> str1.compareTo(str2));


        //BinaryOperator返回的结果,是有minBy的参数Comparator决定的,也就是比较大小,取较小的那个字符串
        System.out.println(binaryOperator.apply("hello", "abcdef"));


    }
}
输出:
abcdef

BiConsumer

接收两个参数,不返回值

@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u);
}

举例:

(key, value) -> System.out.println(key + ” : ” + value)

接收两个参数,不返回值,符合BiConsumer定义

public class LambdaTest {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>(2);

        map.put("java8", "netty");
        map.put("jvm", "nodejs");
        map.put("hbase", "spring");

        map.forEach((key, value) -> System.out.println(key + " : " + value));
    }
}
输出:
jvm : nodejs
java8 : netty
hbase : spring

以上就是常用的函数式接口,函数式接口还是很容易理解和使用的,函数式接口可以用lambda表达式来创建,之前的例子中,都是用的是常规的,符合标准形式(或简写)的lambda表达式。下一节介绍方法引用。

(Type1 param1, Type2 param2......) -> { body }

Optional

Optional是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
可以类比基本数据类型的包装类,Optional可以包装任何值,并且可以通过isPresent()判断是否值存在

public class OptionalTest {

    public static void main(String[] args) {

        Optional<String> optional = Optional.of("optional");

        if(optional.isPresent()){
            System.out.println(optional.get());
        }
    }
}
输出:
optional

上面的例子并不是推荐的写法,因为上面的这种写法和之前的写法没有本质区别:

public class OptionalTest {

    public static void main(String[] args) {

        String str = "optional";

        if(null != str){
            System.out.println(str);
        }
    }
}
输出:
optional

推荐的写法如下:


    public static void main(String[] args) {

        Optional<String> optional = Optional.of("optional");

        //为空则不做任何操作
        optional.ifPresent(System.out::println);
    }
}
输出:
optional

orElse 如果Optional包装的值为空,用默认值来替代

public class OptionalTest {

    public static void main(String[] args) {

        //创建一个包装了空值的Optional
        Optional<String> optional = Optional.empty();

        //为空则用默认值替代
        System.out.println(optional.orElse("java8"));
    }
}
输出:
java8

orElseGet 或者如果Optional包装的值为空,提供一个Supplier,从Supplier获取值

public class OptionalTest {

    public static void main(String[] args) {

        //创建一个包装了空值的Optional
        Optional<String> optional = Optional.empty();

        //为空则使用用户提供的Supplier获取值
        System.out.println(optional.orElseGet(()->"hello world"));
    }
}
输出:
hello world

Optional.of(object) object一定不能为空,如果不能确定object是否为空,可以用Optional.ofNullable(object) 

不要将Optional做为方法的参数,或者类的成员变量,Optional没有实现序列化,Optional一般只做为方法的返回值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值