最近在学习使用guava, 一个非常优秀的开源项目,是对jdk一个非常有力的补充,我看上guava的是能使代码更简洁,良好的代码风格
首先来介绍一下com.google.common.base包中的常用类
1 Function
guava提供了类函数式的编程,其中的代码就是提供了Function, Predicate接口,及工具类Functions, Predicates
Function 主要用来不同类型的对象之间的转换,下面是一个demo
首先定义一个JavaBean
class User { private String username; private String sex; public User (String username, String sex) { this.username = username; this.sex = sex; } void setUsername(String username) { this.username = username; } void setSex(String sex) { this.sex = sex; } String getUsername() { return username; } String getSex() { return sex; } }
然后写测试方法:
public static void main (String[] args) { User u1 = new User("malone", "man"); User u2 = new User("lanlan", "woman"); List<User> list = Lists.newArrayList(u1, u2); Collection<String> result = Collections2.transform(list, new Function<User, String> () { @Override public String apply(User user) { if (Objects.equals(user, null)) { return ""; } return user.toString(); } }); }
使用guava提供的工具类调用transform方法,可实现User到String的集合转换,实际上转换时,调用的是apply方法,工具类Lists,Maps均可接收Function参数,来实现对象转换;如果需要多次转换,可以使用Functions把多个Function整合到一起
可以使用Function作为参数的工具类有:Collections2,Lists, Maps, Iterators
2 Predicate
此接口的实现主要是用来过滤集合中不需要的对象,下面是一个demo
Collection<User> resultUser = Collections2.filter(list, new Predicate<User>() { @Override public boolean apply(User user) { if (Objects.equals(user, null)) { return false; } if (Objects.equals(user.getSex(), "woman")) { return false; } return true; } });
想要过滤掉的对象,只要在apply中判断对应的逻辑,想过滤掉的对象返回false,即不存在结果集中
3 Functions toStringFunction() :返回 Function<Object, String> ,该 Function 的 apply(Object o) 方法调用了参数 o 的 toString() 方法。 apply(Object o) 的参数 o 如果为 null ,会抛出异常。 identity() :返回 Function<E, E> ,该 Function 的 apply(Object o) 方法直接返回参数 o 。forMap(Map<K, V> map) :返回 Function<K, V> ,该 Function 的 apply(K key) 方法在 map 中查找键值为参数 key 的 value ,并返回 value ,如果 key 不在 map 中会抛出异常。
forMap(Map<K, ? extends V> map , @Nullable V defaultValue) :与上面的方法类似,但是如果 apply() 方法的参数 key 不在 map 中,会返回 defaultValue 。
compose(Function<B, C> g, Function<A, ? extends B> f) :返回 Function<A, C> ,该 Function 定义的方法是方法 g 和方法 f 的组合,对于输入参数,先对其调用方法 f ,然后对结果调用方法 g 。
forPredicate(Predicate<T> predicate) :返回 Function<T, Boolean> ,将一个 Predicate 转换为 Function ,该 Function 返回值与 Predicate 相同。
constant(@Nullable E value) :返回 Function<Object, E> ,该 Function 返回常量 value 。
下面是一个demo
public static void main (String[] args) { User u1 = new User("malone", "man"); User u2 = new User("lanlan", "woman"); List<User> list = Lists.newArrayList(u1, u2); Function<User, String> f1 = new Function<User, String> () { @Override public String apply(User user) { if (Objects.equals(user, null)) { return ""; } return user.getUsername(); } }; //多个工具类均可使用类函数式编程 Collection<String> result = Collections2.transform(list, f1); List<String> strList = Lists.transform(list, f1); Iterators.transform(list.iterator(), f1); Function<String, String> f2 = new Function<String, String> () { @Override public String apply(String input) { if (Objects.equals(input, "malone")) { return "malone's function"; } else { return "lanlan's function"; } } }; //连接多个Function Function<User, String> f3 = Functions.compose(f2, f1); List<String> mylist = Lists.transform(list, f3); System.out.println(mylist.get(0)); Map<String, String> map = Maps.newHashMap(); map.put("1", "2"); //Functions可以转换一下map,使用语义更直白的代码,并提供默认值支持 Function<String, String> lookup = Functions.forMap(map, "default value"); System.out.println(lookup.apply("hi")); }
4 Predicates 常用方法
and(), or() 下面是一个demo
public static void main (String[] args) { User u1 = new User("malone", "man"); User u2 = new User("lanlan", "woman"); User u3 = new User("mama", "woman"); List<User> userList = Lists.newArrayList(u1, u2, u3); Predicate<User> p1 = new Predicate<User> () { @Override public boolean apply(User user) { if (user == null) { return false; } if (Objects.equals(user.getUsername(), "malone")) { return false; } return false; } }; Predicate<User> p2 = new Predicate<User> () { @Override public boolean apply(User user) { if (user == null) { return false; } if (Objects.equals(user.getUsername(), "lanlan")) { return false; } return false; } }; //同时判断是否满足两个Predicate Predicate<User> unionPredicate = Predicates.and(p1, p2); List<User> newUserList = Lists.newArrayList(Iterators.filter(userList.iterator(), unionPredicate)); System.out.println(newUserList.size()); //判断是否满足两个Predicate的任何一个 Predicate<User> unionPredicate1 = Predicates.or(p1, p2); List<User> newUserList1 = Lists.newArrayList(Iterators.filter(userList.iterator(), unionPredicate1)); System.out.println(newUserList1.size()); }
and方法的作用是要满足所有and参数的Predicate逻辑才会返回true
or方法的作用是要满足and参数的Predicate任意一个逻辑才会返回true
5 Converter
前面说到的Function用在集合中的对象互相转换上,那么单个对象的转换函数式支持呢,就是使用Converter
首先在增加一个dto的定义UserDto:
class UserDto { private String name; private String userSex; public UserDto() {} public UserDto(String name, String userSex) { this.name = name; this.userSex = userSex; } void setName(String name) { this.name = name; } void setUserSex(String userSex) { this.userSex = userSex; } String getName() { return name; } String getUserSex() { return userSex; } }自定义Converter继承Converter类,需要实现doForward(正向转换), doBackward(反向转换)
public static void main (String[] args) { User user = new User("malone", "man"); //自定义一个Converter Converter<User, UserDto> convertA = new Converter<User, UserDto>() { @Override protected UserDto doForward(User user) { UserDto dto = new UserDto(); if (Objects.equals(user, null)) { return dto; } dto.setName(user.getUsername()); dto.setUserSex(user.getSex()); return dto; } @Override protected User doBackward(UserDto userDto) { User user = new User(); if (Objects.equals(userDto, null)) { return user; } user.setSex(userDto.getUserSex()); user.setUsername(userDto.getName()); return user; } }; //自定义一个Converter Converter<UserDto, String> convertB = new Converter<UserDto, String> () { @Override protected String doForward(UserDto userDto) { if (Objects.equals(userDto, null)) { return "null"; } return userDto.getName() + "|" + userDto.getUserSex(); } @Override protected UserDto doBackward(String s) { if (Objects.equals(s, null)) { return new UserDto("", ""); } List<String> list = Splitter.on("|").splitToList(s); return new UserDto(list.get(0), list.get(1)); } }; //把两个Converter连接成一个转换链条 Converter<User, String> converC = convertA.andThen(convertB); String userStr = converC.convert(user); System.out.println(userStr); //使用Converse方法实现反转换 User newUser = converC.reverse().convert(userStr); System.out.println(newUser.getUsername() + "|" + newUser.getSex()); }调用andThen方法可以连接多个Converter弄一个转换链条,这个方法的名字起得真奇葩 converse方法Converter<A,B>变成Converter<B,A> Converter<A,B> 实现了Function接口,可以在使用Function的地方使用,不过Converter已经废弃了
apply方法,不过从源码可以知道,apply的实现是调用了Convert方法