Guava 18: What’s New? – Guava 18: What’s New?

最后修改: 2015年 12月 24日


1. Overview


Google Guava provides libraries with utilities that ease Java development. In this tutorial we will take a look to new functionality introduced in the Guava 18 release.

Google Guava提供了带有实用程序的库,以简化Java开发。在本教程中,我们将了解一下Guava 18版本中引入的新功能。

2. MoreObjects Utility Class


Guava 18 saw the addition of the MoreObjects class, which contains methods that do not have equivalents in java.util.Objects.

Guava 18增加了MoreObjects类,它包含了一些在java.util.Objects中没有对应的方法。

As of release 18, it only contains implementations of the toStringHelper method, which can be used to help you to build your own toString methods.


  • toStringHelper(Class<?> clazz)
  • toStringHelper(Object self)
  • toStringHelper(String className)

Typically, toString() is used when you need to output some information about an object. Usually it should contain details about the current state of the object. By using one of the implementations of toStringHelper, you can easily build a useful toString() message.

通常, toString()在你需要输出一个对象的一些信息时被使用。通常它应该包含关于该对象当前状态的细节。通过使用toStringHelper的某个实现,你可以轻松地构建一个有用的toString()信息。

Suppose we have a User object containing a few fields that need to be written when toString() is called. We can use the MoreObjects.toStringHelper(Object self) method to do this easily.

假设我们有一个User对象,其中包含一些字段,当toString()被调用时,这些字段需要被写入。我们可以使用MoreObjects.toStringHelper(Object self)方法来轻松做到这一点。

public class User {

    private long id;
    private String name;

    public User(long id, String name) { = id; = name;

    public String toString() {
        return MoreObjects.toStringHelper(this)
            .add("id", id)
            .add("name", name)

Here we have used toStringHelper(Object self) method. With this setup, we can create a sample user to see the output that results when calling toString().

这里我们使用了toStringHelper(Object self)方法。有了这个设置,我们可以创建一个样本用户,看看调用toString()时的输出结果。

User user = new User(12L, "John Doe");
String userState = user.toString();
// userState: User{ id=12,name=John Doe }

The other two implementations will return the same String if configured similarly:


toStringHelper(Class<?> clazz)

toStringHelper(Class<?> clazz)

public String toString() {
    return MoreObjects.toStringHelper(User.class)
        .add("id", id)
        .add("name", name)

toStringHelper(String className)

toStringHelper(String className)

public String toString() {
    return MoreObjects.toStringHelper("User")
        .add("id", id)
        .add("name", name)

The difference between these methods is evident if you call toString() on extensions of the User class. For example, if you have two kinds of Users: Administrator and Player, they would produce different output.


public class Player extends User {
    public Player(long id, String name) {
        super(id, name);

public class Administrator extends User {
    public Administrator(long id, String name) {
        super(id, name);

If you use toStringHelper(Object self) in the User class then your Player.toString() will return “Player{id=12, name=John Doe}“. However, if you use toStringHelper(String className) or toStringHelper(Class<?> clazz), Player.toString() will return “User{id=12, name=John Doe}“. The class name listed will be the parent class rather than the subclass.

如果你在用户类中使用toStringHelper(Object self),那么你的Player.toString()将返回”Player{id=12, name=John Doe}“。然而,如果你使用toStringHelper(String className)或者toStringHelper(Class<?> clazz)Player.toString()将返回”User{id=12, name=John Doe}“。列出的类名将是父类而不是子类。

3. New Methods in FluentIterable


3.1. Overview


FluentIterable is used to operate with Iterable instances in a chained fashion. Lets see how it can be used.


Suppose you have list of User objects, defined in the examples above, and you wish to filter that list to include only the users that are aged 18 or older.


List<User> users = new ArrayList<>();
users.add(new User(1L, "John", 45));
users.add(new User(2L, "Michelle", 27));
users.add(new User(3L, "Max", 16));
users.add(new User(4L, "Sue", 10));
users.add(new User(5L, "Bill", 65));

Predicate<User> byAge = user -> user.getAge() >= 18;

List<String> results = FluentIterable.from(users)

The resulting list will contain the information for John, Michelle, and Bill.


3.2. FluentIterable.of(E[])

3.2. FluentIterable.of(E[])

With this method. you can create a FluentIterable from array of Object.


User[] usersArray = { new User(1L, "John", 45), new User(2L, "Max", 15) } ;
FluentIterable<User> users = FluentIterable.of(usersArray);

You can now use the methods provided in FluentIterable interface.


3.3. FluentIterable.append(E…)

3.3. FluentIterable.append(E..)

You can create new FluentIterable from existing FluentIterable by appending more elements to it.


User[] usersArray = {new User(1L, "John", 45), new User(2L, "Max", 15)};

FluentIterable<User> users = FluentIterable.of(usersArray).append(
                                 new User(3L, "Sue", 23),
                                 new User(4L, "Bill", 17)

As expected, the size of the resultant FluentIterable is 4.


3.4. FluentIterable.append(Iterable<? extends E>)

3.4. FluentIterable.append(Iterable<? extends E>)

This method behaves the same as the previous example, but allows you to add the entire contents of any existing implementation of Iterable to a FluentIterable.


User[] usersArray = { new User(1L, "John", 45), new User(2L, "Max", 15) };

List<User> usersList = new ArrayList<>();
usersList.add(new User(3L, "Diana", 32));

FluentIterable<User> users = FluentIterable.of(usersArray).append(usersList);

As expected, the size of the resultant FluentIterable is 3.


3.5. FluentIterable.join(Joiner)

3.5. FluentIterable.join(Joiner)

The FluentIterable.join(…) method produces a String representing the entire contents of the FluentIterable, joined by a given String.

FluentIterable.join(…) 方法产生一个String,代表FluentIterable的全部内容,由一个给定的String连接。

User[] usersArray = { new User(1L, "John", 45), new User(2L, "Max", 15) };
FluentIterable<User> users = FluentIterable.of(usersArray);
String usersString = users.join(Joiner.on("; "));

The usersString variable will contain the output of calling the toString() method on each element of the FluentIterable, separated by a “;”. The Joiner class provides several options for joining the strings.


4. Hashing.crc32c


A hash function is any function that can be used to map data of arbitrary size to data of a fixed size. It is used in many areas, such as cryptography and checking for errors in transmitted data.


The Hashing.crc32c method returns a HashFunction that implements the CRC32C algorithm.


int receivedData = 123;
HashCode hashCode = Hashing.crc32c().hashInt(receivedData);
// hashCode: 495be649

5. InetAddresses.decrement(InetAddress)


This method returns a new InetAddress that will be “one less” than its input.

该方法返回一个新的InetAddress,该地址将比其输入值 “少一个”。

InetAddress address = InetAddress.getByName("");
InetAddress decrementedAddress = InetAddresses.decrement(address);
// decrementedAddress:

6. New Executors in MoreExecutors


6.1. Threading Review


In Java you can use multiple threads to execute work. For this purpose, Java has Thread and Runnable classes.


ConcurrentHashMap<String, Boolean> threadExecutions = new ConcurrentHashMap<>();
Runnable logThreadRun = () -> threadExecutions.put(Thread.currentThread().getName(), true);

Thread t = new Thread(logThreadRun);;

Boolean isThreadExecuted = threadExecutions.get("main");

As expected, isThreadExecuted will be true. Also you can see that this Runnable will run only in the main thread. If you want to use multiple threads, you can use different Executors for different purposes.


ExecutorService executorService = Executors.newFixedThreadPool(2);

Boolean isThread1Executed = threadExecutions.get("pool-1-thread-1");
Boolean isThread2Executed = threadExecutions.get("pool-1-thread-2");
// isThread1Executed: true
// isThread2Executed: true

In this example, all submitted work is executed in ThreadPool threads.


Guava provides different methods in its MoreExecutors class.


6.2. MoreExecutors.directExecutor()


This is a lightweight executor that can run tasks on the thread that calls the execute method.


Executor executor = MoreExecutors.directExecutor();

Boolean isThreadExecuted = threadExecutions.get("main");
// isThreadExecuted: true

6.3. MoreExecutors.newDirectExecutorService()


This method returns an instance of ListeningExecutorService. It is a heavier implementation of Executor that has many useful methods. It is similar to the deprecated sameThreadExecutor() method from previous versions of Guava.


This ExecutorService will run tasks on the thread that calls the execute() method.


ListeningExecutorService executor = MoreExecutors.newDirectExecutorService();

This executor has many useful methods such as invokeAll, invokeAny, awaitTermination, submit, isShutdown, isTerminated, shutdown, shutdownNow.

这个执行器有许多有用的方法,如invokeAll, invokeAny, awaitTermination, submit, isShutdown, isTerminated, shutdown, shutdownNow

7. Conclusion


Guava 18 introduced several additions and improvements to its growing library of useful features. It is well-worth considering for use in your next project. The code samples in this article are available in the GitHub repository.

Guava 18在其不断增长的有用功能库中引入了一些新增功能和改进。它非常值得考虑在你的下一个项目中使用。本文中的代码样本可在GitHub资源库中找到。