首页 > 代码库 > Java8 Lambda表达式介绍 -- 写给Guava使用者
Java8 Lambda表达式介绍 -- 写给Guava使用者
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.7public static <T> T requireNonNull(T obj, String message) // @since 1.7public 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的函数式编程变的多余。
HashMultimap
假设我们想按照玩家的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); } }现在,可以用Lambda表达式来更清晰的表达意图:
public void groupingByJava8(List<Player> players) { Map<Integer, List<Player>> groups = players.stream() .collect(Collectors.groupingBy(Player::getGroupId)); }
结论
Guava是一个很好的库,但是随着Java自身的改进,Guava的很多功能已经变得多余。
Java8 Lambda表达式介绍 -- 写给Guava使用者