在一般的开发过程中我们的函数式编程都是通过匿名类进行传输函数。对于一个不会复用且不易命名或者不好放进某个具体的类中的临时方法。我们都可以使用匿名函数对象来进行处理。而JDK8对开发中比较常见的几种情况提供了一系列通用的函数对象。
订单类:
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进行临时的处理。
以下我们通过消费一个订单,我们的处理逻辑是将订单中的所有商品都优惠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对象进行链式处理。
当我们需要返回特定泛型的匿名函数时,可以使用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()); } }
当我们需要既对泛型参数进行处理,并返回另一个泛型参数时,可以使用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对象筛选出价格大于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); } }