JDK8 函数式编程

函数式编程

为什么需要函数式编程?

在一般的开发过程中我们的函数式编程都是通过匿名类进行传输函数。对于一个不会复用且不易命名或者不好放进某个具体的类中的临时方法。我们都可以使用匿名函数对象来进行处理。而JDK8对开发中比较常见的几种情况提供了一系列通用的函数对象。

四个主要的函数式对象
  • Consumer : 描述消费泛型T对象且无返回值的匿名函数。
  • Supplier : 描述有返回值为泛型T对象的匿名函数。
  • Function : 描述输入泛型T,返回泛型R的匿名函数。
  • Predicate: 描述匿名的条件判断。
我们以订单以及订单中的商品举例来说明以下四种函数对象

订单类:

public class Order {
    private List<Item> itemList;
    public List<Item> getItemList() {
        return itemList;
    }
    public void setItemList(List<Item> itemList) {
        this.itemList = itemList;
    }
}

商品类:

public class Item {

    private String productName;

    private Integer price;

    public Item(){

    }

    public Item(String productName, Integer price) {

        this.productName = productName;
        this.price = price;

    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Item{" +
                "productName='" + productName + '\'' +
                ", price=" + price +
                '}';
    }
}

为了方便生成测试订单,做了一个测试基类


public class AbstractTest {

    protected static Order getTestOrder() {

        Order order = new Order();

        List<Item> itemList = new ArrayList<>();

        Item item1 = new Item("键盘", 16);
        Item item2 = new Item("鼠标", 32);
        Item item3 = new Item("笔记本支架", 25);

        itemList.add(item1);
        itemList.add(item2);
        itemList.add(item3);

        order.setItemList(itemList);

        return order;

    }


}

Consumer

当你需要对某个泛型对象进行处理,并没有需要返回的值的话我们可以使用Consumer进行临时的处理。

以下我们通过消费一个订单,我们的处理逻辑是将订单中的所有商品都优惠3块钱。

public class ConsumerTest extends AbstractTest {


    /**
     * 调用accept方法接收order对象,具体操作交给匿名函数对象
     *
     * @param order
     * @param orderConsumer
     */
    public static void consume(Order order, Consumer<Item> orderConsumer) {

        List<Item> itemList = order.getItemList();

        if (itemList == null || itemList.isEmpty()) {
            return;
        }

        for (Item item : itemList) {
            orderConsumer.accept(item);
        }

    }


    public static void main(String[] args) {

        // 对订单中的商品进行优惠处理
        consume(getTestOrder(), item -> item.setPrice(item.getPrice() - 3));

    }


}

Consumer对象还可以有andThen()方法,继续传入Consumer对象进行链式处理。

Supplier

当我们需要返回特定泛型的匿名函数时,可以使用Supplie对象

在下面的例子中,我们通过Supplier中的逻辑返回每个商品的价格


public class SupplierTest extends AbstractTest{


    /**
     * 提取商品的价格
     * @param item
     * @param supplier
     * @return
     */
    public static Integer getPrice(Item item, Supplier<Integer> supplier) {

        return supplier.get();

    }


    public static void main(String[] args) {

        Order order = getTestOrder();

        List<Item> itemList = order.getItemList();

        if (itemList == null || itemList.isEmpty()) {
            return;
        }

        List<Integer> priceList = new ArrayList<>();

        for (Item item : itemList) {
            priceList.add(getPrice(item, () -> item.getPrice()));
        }


        System.out.println(priceList.toString());

    }


}

Function

当我们需要既对泛型参数进行处理,并返回另一个泛型参数时,可以使用Funciton这个函数对象。

在以下我们通过Function解析商品描述字符串并返回商品对象


public class FunctionTest extends AbstractTest {

    /**
     * 通过商品描述字符串解析并返回商品对象
     *
     * @param itemStr
     * @param function
     * @return
     */
    public static Item getItem(String itemStr, Function<String, Item> function) {

        return function.apply(itemStr);

    }


    public static void main(String[] args) {

        List<String> itemStrList = new ArrayList<>();

        itemStrList.add("苹果,22");
        itemStrList.add("香蕉,33");
        itemStrList.add("橘子,12");

        List<Item> itemList = new ArrayList<>();

        for (String itemStr : itemStrList) {

            itemList.add(getItem(itemStr, s -> {

                String[] split = itemStr.split(",");

                return new Item(split[0], Integer.valueOf(split[1]));

            }));

        }

        System.out.println(itemList);

    }

}

在Stream流当中Function经常用来将参数对象转换为特定对象进行返回

Predicate

当我们需要将特定的判断表达式通过函数对象进行传入的时候,可以使用Predicate对象。

以下我们通过Predicate对象筛选出价格大于30的商品

public class PredicateTest extends AbstractTest {


    public static void findExpensiveItem(Order order, Predicate<Item> predicate) {

        List<Item> itemList = order.getItemList();

        if (itemList == null || itemList.size() == 0) {
            return;
        }

        for (Item item : itemList) {

            if (predicate.test(item)) {
                System.out.println(item);
            }

        }

    }

    public static void main(String[] args) {
        // 找出价钱大于30的商品
        findExpensiveItem(getTestOrder(), item -> item.getPrice() > 30);

    }

}

笔者个人总结,如有错误恳请网友评论指正。


标题:JDK8 函数式编程
作者:valarchie
地址:http://vc2x.com/articles/2020/07/25/1595650203254.html
技术讨论群:1398880
本文为博主原创文章,转载请附上原文出处链接。