1. Обзор
Google Guava предоставляет библиотекам утилиты, облегчающие разработку Java. В этом уроке мы рассмотрим новые функции, представленные в выпуске Guava 18 .
2. Служебный класс MoreObjects
В Guava 18 был добавлен класс MoreObjects
, который содержит методы, не имеющие эквивалентов в java.util.Objects
.
Начиная с версии 18, он содержит только реализации метода toStringHelper
, которые можно использовать для создания собственных методов toString .
toStringHelper(Класс<?> clazz)
toStringHelper (собственный объект)
toStringHelper (строковое имя класса)
Обычно toString()
используется, когда вам нужно вывести некоторую информацию об объекте .
Обычно он должен содержать сведения о текущем состоянии объекта. Используя одну из реализаций toStringHelper
, вы можете легко создать полезное сообщение toString()
.
Предположим, у нас есть объект 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();
}
}
Здесь мы использовали метод toStringHelper(Object self) .
С помощью этой настройки мы можем создать тестового пользователя, чтобы увидеть вывод, который получается при вызове toString()
.
User user = new User(12L, "John Doe");
String userState = user.toString();
// userState: User{ id=12,name=John Doe }
Две другие реализации вернут одну и ту же строку
, если настроены аналогично:
toStringHelper(Класс<?> clazz)
@Override
public String toString() {
return MoreObjects.toStringHelper(User.class)
.add("id", id)
.add("name", name)
.toString();
}
toStringHelper (строковое имя класса)
@Override
public String toString() {
return MoreObjects.toStringHelper("User")
.add("id", id)
.add("name", name)
.toString();
}
Разница между этими методами очевидна, если вы вызываете toString()
для расширений класса User
. Например, если у вас есть два типа User
s: Administrator
и Player
, они будут производить разные выходные данные. ``
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);
}
}
Если вы используете toStringHelper(Object self)
в классе User
, то ваш Player.toString()
вернет « Player{id=12, name=John Doe}
». Однако, если вы используете toStringHelper(String className)
или toStringHelper(Class<?> clazz)
, Player.toString()
вернет « User{id=12, name=John Doe}
». Указанное имя класса будет родительским классом, а не подклассом.
3. Новые методы в FluentIterable
3.1. Обзор
FluentIterable
используется для работы с экземплярами Iterable в цепочке.
Давайте посмотрим, как это можно использовать.
Предположим, у вас есть список объектов 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();
Полученный список будет содержать информацию для Джона, Мишель и Билла.
3.2. FluentIterable.of(E[])
С помощью этого метода. вы можете создать FluentIterable
из массива Object
.
User[] usersArray = { new User(1L, "John", 45), new User(2L, "Max", 15) } ;
FluentIterable<User> users = FluentIterable.of(usersArray);
Теперь вы можете использовать методы, представленные в интерфейсе FluentIterable
.
3.3. FluentIterable.append(E…)
Вы можете создать новый 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)
);
Как и ожидалось, размер результирующего FluentIterable
равен 4.
3.4. FluentIterable.append(Iterable<? расширяет E>)
Этот метод ведет себя так же, как и предыдущий пример, но позволяет добавить все содержимое любой существующей реализации 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);
Как и ожидалось, размер результирующего FluentIterable
равен 3.
3.5. FluentIterable.join (соединитель)
Метод FluentIterable.join(…)
создает строку
, представляющую все содержимое FluentIterable
, объединенное заданной строкой
.
User[] usersArray = { new User(1L, "John", 45), new User(2L, "Max", 15) };
FluentIterable<User> users = FluentIterable.of(usersArray);
String usersString = users.join(Joiner.on("; "));
Переменная usersString
будет содержать выходные данные вызова метода toString()
для каждого элемента FluentIterable
, разделенные символом «;». Класс Joiner
предоставляет несколько вариантов соединения строк.
4. Хеширование.crc32c
Хэш-функция — это любая функция, которую можно использовать для сопоставления данных произвольного размера с данными фиксированного размера. Он используется во многих областях, таких как криптография и проверка на наличие ошибок в передаваемых данных.
Метод Hashing.crc32c
возвращает HashFunction
, реализующую алгоритм CRC32C .
int receivedData = 123;
HashCode hashCode = Hashing.crc32c().hashInt(receivedData);
// hashCode: 495be649
5. InetAddresses.decrement(InetAddress)
Этот метод возвращает новый InetAddress
, который будет «на один меньше», чем его вход.
InetAddress address = InetAddress.getByName("127.0.0.5");
InetAddress decrementedAddress = InetAddresses.decrement(address);
// decrementedAddress: 127.0.0.4
6. Новые исполнители в MoreExecutors
``
6.1. Обзор потоков
В Java вы можете использовать несколько потоков для выполнения работы. Для этого в Java есть классы Thread
и Runnable .
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");
Как и ожидалось, isThreadExecuted
будет иметь значение true
. Также вы можете видеть, что этот Runnable
будет работать только в основном
потоке. Если вы хотите использовать несколько потоков, вы можете использовать разные Исполнители
для разных целей.
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
В этом примере вся отправленная работа выполняется в потоках ThreadPool .
Guava предоставляет различные методы в своем классе MoreExecutors
.
6.2. MoreExecutors.directExecutor()
Это облегченный исполнитель, который может запускать задачи в потоке, вызывающем метод execute
.
Executor executor = MoreExecutors.directExecutor();
executor.execute(logThreadRun);
Boolean isThreadExecuted = threadExecutions.get("main");
// isThreadExecuted: true
6.3. MoreExecutors.newDirectExecutorService()
Этот метод возвращает экземпляр ListeningExecutorService
. Это более тяжелая реализация Executor
, которая имеет много полезных методов. Он похож на устаревший метод sameThreadExecutor()
из предыдущих версий Guava.
Этот ExecutorService
будет запускать задачи в потоке, вызывающем метод execute()
.
ListeningExecutorService executor = MoreExecutors.newDirectExecutorService();
executor.execute(logThreadRun);
Этот исполнитель имеет много полезных методов, таких как invokeAll, invokeAny, awaitTermination, submit, isShutdown, isTerminated, shutdown, shutdownNow
.
7. Заключение
Guava 18 представила несколько дополнений и улучшений в своей растущей библиотеке полезных функций. Это стоит рассмотреть для использования в вашем следующем проекте. Примеры кода в этой статье доступны в репозитории GitHub .