Guava
Guava是Google公司开源的一个实用工具库,对Java类库进行了多方面的增强。比如说,对函数式编程的支持,新的集合类(Multimap等),Cache支持,等等。在Java8之前,Guava和Java之间的关系,可以表示成下面这幅图:
但是随着Java8的发布,Guava和Java的关系发生了一些改变。Guava提供的很多功能,被内置在了Java8里,如下图所示:
本文举了几个例子,用代码来说明原先需要借助Guava来实现的功能,如何用Java7或Java8实现。
Joiner
Joiner用来拼接n个字符串,下面是一个例子:
@Test
public void joinerGuava() {
List<String> strList = Arrays.asList("one", "two", "three", null);
String csv = Joiner.on(",")
.skipNulls()
.join(strList);
assertEquals("one,two,three", csv);
}
在Java8里,我们可以借助Lambda表达式来做同样的事情:
@Test
public void joinerJava8() {
List<String> strList = Arrays.asList("one", "two", "three", null);
String csv = strList.stream()
.filter(Objects::nonNull)
.collect(Collectors.joining(","));
assertEquals("one,two,three", csv);
}
Ordering
Guava提供了Ordering类以方便我们创建Comparator,下面是一段示例代码:
class Player {
private String name;
public String getName() {
return name;
}
}
public void orderingGuava() {
// public abstract class Ordering<T> implements Comparator<T>
Ordering<Player> ordering = Ordering.natural().nullsFirst().onResultOf(new Function<Player, String>() {
@Override
public String apply(Player foo) {
return foo.getName();
}
});
}
在Java8里,我们可以这样做:
public void comparingJava8() {
Comparator<Player> cmp = Comparator.comparing(Player::getName,
Comparator.nullsFirst(Comparator.naturalOrder()));
}
Optional
Optional可以显式的指出一个引用可能是null,下面是从Guava文档里抄到的例子:
// Guava
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
用
java.util.Optional可以做类似的事情,而且方法也大同小异,这里就不贴代码了。
Preconditions.checkNotNull()
如果想保证一个引用不是null(尽早抛出NullPointerException),可以像下面这样写:
class Player {
private final String name;
public Player(String name) {
this.name = Preconditions.checkNotNull(name);
}
}
checkNotNull()方法一共有三个版本:
public static <T> T checkNotNull(T reference)
public static <T> T checkNotNull(T reference, Object errorMessage)
public static <T> T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs)
java.util.Objects提供了三个类似的方法:
public static <T> T requireNonNull(T obj) // @since 1.7
public static <T> T requireNonNull(T obj, String message) // @since 1.7
public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier) // @since 1.8
Guava Objects
com.google.common.base.Objects类里的一些方法,可以替换成java.util.Objects里的方法,比如:
// com.google.common.base.Objects
public static boolean equal(@Nullable Object a, @Nullable Object b)
public static int hashCode(@Nullable Object... objects)
可以用下面的方法替换:
// java.util.Objects
public static boolean equals(Object a, Object b) // @since 1.7
public static int hashCode(Object o) // @since 1.7
public static int hash(Object... values) // @since 1.7
函数式编程
很多人使用Guava的直接原因,可能就是想更好的进行函数式编程。为了支持函数式编程,Guava提供了下面这两个接口:
public interface Function<F, T> {
@Nullable T apply(@Nullable F input);
}
public interface Predicate<T> {
boolean apply(@Nullable T input);
}
Guava的各种集合帮助类都提供了大量使用上面两个接口的方法,比如Iterables、Collections2、Maps等等。但是Guava的函数式编程,仍然是建立在Java匿名类的语法之上,虽然一定程度上降低了代码的丑陋程度,但是仍然不够理想。Java8的出现,彻底让Guava的函数式编程变的多余。
Multimap
假设我们想按照玩家的groupId来给玩家分组,Java8以前,可以这样做:
public void mapListJava7(List<Player> players) {
Map<Integer, List<Player>> groups = new HashMap<>();
for (Player player : players) {
List<Player> group = groups.get(player.getGroupId());
if (group == null) {
group = new ArrayList<>();
groups.put(player.getGroupId(), group);
}
group.add(player);
}
}
如果用Guava的Multimap,代码就会清晰很多:
public void guavaMultimap(List<Player> players) {
Multimap<Integer, Player> groups = ArrayListMultimap.create();
for (Player player : players) {
groups.put(player.getGroupId(), player);
}
}
Java8给Map添加了getOrDefault()方法,所以即使不用Lambda,代码也会简单一点:
public void mapListJava8(List<Player> players) {
Map<Integer, List<Player>> groups = new HashMap<>();
for (Player player : players) {
List<Player> group = groups.getOrDefault(player.getGroupId(), new ArrayList<>());
group.add(player);
}
}
当然,可以用Lambda表达式来更清晰的表达意图:
public void groupingByJava8(List<Player> players) {
Map<Integer, List<Player>> groups = players.stream()
.collect(Collectors.groupingBy(Player::getGroupId));
}
结论
Guava是一个很好的库,但是随着Java自身的改进,Guava的很多功能已经变得多余。