最近在学习使用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方法