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

最后修改: 2015年 12月 24日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

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

2.MoreObjects实用类

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.

从第18版开始,它只包含toStringHelper方法的实现,它可以用来帮助你建立你自己的toString方法。

  • 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) {
        this.id = id;
        this.name = name;
    }

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

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:

如果配置类似,其他两个实现将返回相同的String

toStringHelper(Class<?> clazz)

toStringHelper(Class<?> clazz)

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

toStringHelper(String className)

toStringHelper(String className)

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

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.

如果你在User类的扩展上调用toString(),这些方法的区别就很明显。例如,如果你有两种Users。AdministratorPlayer,它们将产生不同的输出。

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、FluentIterable的新方法

3.1. Overview

3.1.概述

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

FluentIterable被用来以连锁方式操作Iterable实例。让我们看看它是如何被使用的。

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.

假设你有一个User对象的列表,定义在上面的例子中,你希望过滤这个列表,只包括18岁以上的用户。

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)
                           .filter(byAge)
                           .transform(Functions.toStringFunction())
                           .toList();

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.

通过这个方法,你可以从Object阵列中创建一个FluentIterable

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.

你现在可以使用FluentIterable接口中提供的方法。

3.3. FluentIterable.append(E…)

3.3. FluentIterable.append(E..)

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

你可以从现有的FluentIterable中创建新的FluentIterable,向它追加更多的元素。

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.

正如预期的那样,结果FluentIterable的大小为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.

这个方法的行为与前面的例子相同,但允许你将任何现有的Iterable的实现的全部内容添加到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.

正如预期的那样,结果FluentIterable的大小为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.

usersString变量将包含在FluentIterable的每个元素上调用toString()方法的输出,用”;”隔开。Joiner类为连接字符串提供了几个选项。

4. Hashing.crc32c

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.

Hashing.crc32c方法返回一个实现CRC32C算法的HashFunction

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

5. InetAddresses.decrement(InetAddress)

5.InetAddresses.decrement(InetAddress)

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

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

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

6. New Executors in MoreExecutors

6.在MoreExecutors中的新执行者

6.1. Threading Review

6.1.线程回顾

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

在Java中,你可以使用多个线程来执行工作。为此,Java有ThreadRunnable类。

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

Thread t = new Thread(logThreadRun);
t.run();

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.

正如预期的那样,isThreadExecuted将是true。你也可以看到,这个Runnable将只在main线程中运行。如果你想使用多个线程,你可以为不同的目的使用不同的Executors

ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(logThreadRun);
executorService.submit(logThreadRun);
executorService.shutdown();

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.

在这个例子中,所有提交的工作都在ThreadPool线程中执行。

Guava provides different methods in its MoreExecutors class.

Guava在其MoreExecutors类中提供了不同的方法。

6.2. MoreExecutors.directExecutor()

6.2.MoreExecutors.directExecutor()

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

这是一个轻量级的执行器,可以在调用execute方法的线程上运行任务。

Executor executor = MoreExecutors.directExecutor();
executor.execute(logThreadRun);

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

6.3. MoreExecutors.newDirectExecutorService()

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.

该方法返回一个ListeningExecutorService的实例。它是一个更重的Executor的实现,有许多有用的方法。它类似于Guava以前版本中被废弃的sameThreadExecutor()方法。

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

这个ExecutorService将在调用execute()方法的线程上运行任务。

ListeningExecutorService executor = MoreExecutors.newDirectExecutorService();
executor.execute(logThreadRun);

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

7.结论

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资源库中找到。