原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处 。简介java8之后,常用的Map接口中添加了一些非常实用的函数,可以大大简化一些特定场景的代码编写,提升代码可读性,一起来看看吧 。
computeIfAbsent函数比如,很多时候我们需要对数据进行分组,变成
Map<Integer, List<?>>
的形式,在java8之前,一般如下实现:List<Payment> payments = getPayments();Map<Integer, List<Payment>> paymentByTypeMap = new HashMap<>();for(Payment payment : payments){if(!paymentByTypeMap.containsKey(payment.getPayTypeId())){paymentByTypeMap.put(payment.getPayTypeId(), new ArrayList<>());}paymentByTypeMap.get(payment.getPayTypeId()).add(payment);}
可以发现仅仅做一个分组操作,代码却需要考虑得比较细致,在Map中无相应值时需要先塞一个空List进去 。但如果使用java8提供的
computeIfAbsent
方法,代码则会简化很多,如下:List<Payment> payments = getPayments();Map<Integer, List<Payment>> paymentByTypeMap = new HashMap<>();for(Payment payment : payments){paymentByTypeMap.computeIfAbsent(payment.getPayTypeId(), k -> new ArrayList<>()).add(payment);}
computeIfAbsent
方法的逻辑是,如果map中没有(Absent)相应的key,则执行lambda表达式生成一个默认值并放入map中并返回,否则返回map中已有的值 。带默认值Map由于这种需要默认值的Map太常用了,我一般会封装一个工具类出来使用,如下:
public class DefaultHashMap<K, V> extends HashMap<K, V> {Function<K, V> function;public DefaultHashMap(Supplier<V> supplier) {this.function = k -> supplier.get();}@Override@SuppressWarnings("unchecked")public V get(Object key) {return super.computeIfAbsent((K) key, this.function);}}
然后再这么使用,如下:List<Payment> payments = getPayments();Map<Integer, List<Payment>> paymentByTypeMap = new DefaultHashMap<>(ArrayList::new);for(Payment payment : payments){paymentByTypeMap.get(payment.getPayTypeId()).add(payment);}
呵呵,这玩得有点像python的defaultdict(list)
了临时Cache有时,在一个for循环中,需要一个临时的Cache在循环中复用查询结果,也可以使用computeIfAbcent,如下:
List<Payment> payments = getPayments();Map<Integer, PayType> payTypeCacheMap = new HashMap<>();for(Payment payment : payments){PayType payType = payTypeCacheMap.computeIfAbsent(payment.getPayTypeId(),k -> payTypeMapper.queryByPayType(k));payment.setPayTypeName(payType.getPayTypeName());}
因为payments中不同payment的pay_type_id极有可能相同,使用此方法可以避免大量重复查询,但如果不用computeIfAbcent函数,代码就有点繁琐晦涩了 。computeIfPresent函数computeIfPresent函数与computeIfAbcent的逻辑是相反的,如果map中存在(Present)相应的key,则对其value执行lambda表达式生成一个新值并放入map中并返回,否则返回null 。
这个函数一般用在两个集合做等值关联的时候,可少写一次判断逻辑,如下:
@Datapublic static class OrderPayment {private Order order;private List<Payment> payments;public OrderPayment(Order order) {this.order = order;this.payments = new ArrayList<>();}public OrderPayment addPayment(Payment payment){this.payments.add(payment);return this;}}
public static void getOrderWithPayment(){List<Order> orders = getOrders();Map<Long, OrderPayment> orderPaymentMap = new HashMap<>();for(Order order : orders){orderPaymentMap.put(order.getOrderId(), new OrderPayment(order));}List<Payment> payments = getPayments();//将payment关联到相关的order上for(Payment payment : payments){orderPaymentMap.computeIfPresent(payment.getOrderId(),(k, orderPayment) -> orderPayment.addPayment(payment));}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 【JAVA】详解在JAVA中int与Integer的区别以及背后的原因。
- 哪些星座恋爱后特别会说话
- 蛇生肖与什么生肖最配
- 生肖鸡配什么生肖为好人
- 什么生肖鼠配什么生肖好
- 崩坏3永恒的礼堂怎么获取
- 暗黑破坏神:不朽茧中的求救声奇遇事件怎么完成
- 第五人格鹤翁位置在哪
- 射雕英雄传中穆易的真名是什么?
- 小七方冷是什么电视剧中的人物?