最近在开发宝贝化项目过程中,遇到一个问题:同一个车型对应多种价格,需要做过滤处理,保留统一车型最低的价格;看似很简单的问题,但如何优雅的编程,让代码更加简洁,性能更好。对于有代码洁癖的人来说,想到了guava强大的函数处理功能以及Jdk8 stream语法;项目结束之后,想把这个guava函数编程应用总结分享一下
guava的应用场景guava排序功能guava过滤功能jdk8的lambda表达式jdk8的Stream语法前后端分离技术体系redux的应用场景有过这么一句话:当你不知道什么时候用到redux的时候,那就是不需要它。其实在java这种面向对象的编程思想,很少会考虑到函数式编程,主要在于函数式编程不符合面向对象的思想,难以理解,甚至有时候代码阅读非常困难,对于代码的维护那是一件灾难性的事件。所以一般场景不太建议大家用函数式编程。但有些场景比如复杂的数据处理,算法运算等等,这些可以考虑用到guava的函数编程思想。
排序器Ordering是guava流畅风格排序器Comparator的模板实现,用它可以构建复杂的集合排序功能
《一》常见的排序器
方法功能natural()对排序类型自然排序:数字大小、日期先后顺序等usingToString()对字符串进行字典排序arbitrary()无序,每次排序的结果都不相同实现自定义排序器,通常可以使用Ordering.from(Comparator)的方式,或者实现Ordering模板构造
Comparator<String> vr = (s1, s2) -> BigDecimal.valueOf(Double.valueOf(s1)).compareTo(BigDecimal.valueOf(Double.valueOf(s2))); TreeMultimap<Long, String> keyMap = TreeMultimap.create(Ordering.natural(), Ordering.from(vr));示例:
List<String> tlist = Lists.newArrayList(ImmutableList.of("welcome","to","guava","java","lambda")); System.out.println("排序前:" + JSON.toJSONString(tlist)); //排序前:["welcome","to","guava","java","lambda"] tlist = Ordering.usingToString().sortedCopy(tlist); System.out.println("排序后" + JSON.toJSONString(tlist)); //排序后["guava","java","lambda","to","welcome"]《二》链式调用方法:通过链式调用,可以由给定的排序器衍生出其它排序器
方法功能reverse()获取语义相反的排序器nullsFirst()把null值排在最前面nullsLast()把null值排在最后面compound(Comparator)合成另一个比较器,以处理当前排序器中的相等情况onResultOf(Function)对集合中元素调用Function,再按返回值用当前排序器排序示例:
对PriceInfo这个类,对车型carType自然排序,null值排在前面(纯属为了说明用法)
@Data public class PriceInfo { /** * 车型 */ private Long carType; /** * 价格 */ private String price; }实现方式:
Function<PriceInfo, Long> sortCarTypeFunction = new Function<PriceInfo, Long>() { @Override public Long apply(PriceInfo priceInfo) { return priceInfo.getCarType(); } }; Ordering<PriceInfo> carTypeOrdering = Ordering.natural().reverse().nullsFirst().onResultOf(sortCarTypeFunction);我们可以使用com.google.common.collect.Iterables和com.google.common.base.Predicates类来过滤例子中的列表
List<String> filterList = Lists.newArrayList("welcome", "to", "guava", "java", "lambda"); Predicate<String> lessThenPredicate = new Predicate<String>() { @Override public boolean apply(String s) { return s.length() > 5; } }; Iterable<String> filterResult = Iterables.filter(filterList, Predicates.or((Predicates.or(Predicates.equalTo("guava"), Predicates.equalTo("java"))), lessThenPredicate)); Preconditions.checkArgument(Lists.newArrayList(filterResult).containsAll(Lists.newArrayList("guava", "java", "to")), "集合包含:[guava,welcome,lambda,java]");API地址:https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
jdk8引入stream语法主要是为了弥补函数式编程的缺陷,实际上也是借鉴了guava的函数编程风格;stream和I/O不同,它更像具有Iterable的集合类,但行为和集合类又有所不同。整体来讲Stream API包含构建、中间操作、终端操作;
更多Stream功能了解:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
