google guava что это

Путеводитель по таблице Гуава

В этом учебнике мы покажем, как использовать интерфейс таблицы Google Guava и его многочисленные реализации.

1. Обзор

В этом учебнике мы покажем, как использовать google Guava в Таблица интерфейса и его многочисленных реализаций.

Гуава Таблица представляет собой таблицу, похожую на структуру, содержащую строки, столбцы и связанные с ними значения ячеев. Строка и столбец действуют как упорядоченная пара ключей.

2. Таблица Гуавы Google

Давайте посмотрим, как использовать Таблица класс.

2.1. Зависимость от Maven

Начнем с добавления зависимости библиотеки Гуавы от Google в пом.xml :

Если бы мы представляли Гуаву стол использование Коллекции присутствует в ядре Java, то структура будет карта строк, где каждая строка содержит карту столбцов с связанными значениями ячейки.

Таблица представляет собой специальную карту, где два ключа могут быть указаны в комбинированном порядке для обозначения одного значения.

3. Создание

Можно создать экземпляр Таблица несколькими способами:

Использование создать метод из класса HashBasedTable который использует LinkedHashMap внутренне:

Если мы заранее знаем ключи строки и клавиши столбца, а размер стола фиксируется, вспользуйте создать метод из класса ArrayTable :

Если мы намерены создать непреложный экземпляр Таблица чьи внутренние данные никогда не изменятся, используйте Неизменяемый класс (создание, которое следует шаблону строителя):

4. Использование

4.1. Поиск

Если мы знаем ключ строки и ключ столбца, то мы можем получить значение, связанное с строкой и ключом столбца:

4.2. Проверка для входа

Мы можем проверить наличие записи в Таблица на основе:

Давайте посмотрим, как проверить наличие записи:

4.3. Удаление

Мы можем удалить запись из Таблица путем поставки ключа строки и ключа столбца:

4.4. Строка Ключ к карте значения ячейки

Мы можем получить Карта представление ключа в качестве строки и значения в качестве CellValue предоставляя ключ столбца:

4.5. Картографное представление таблицы

Мы можем получить Карта > представление с помощью columnMap метод:

4.6. Колонка Ключ к карте значения ячейки

Мы можем получить Карта представление ключа в качестве столбца и значения в качестве CellValue предоставляя ключ строки:

4.7. Получить отчетливый ключ строки

Мы можем получить все ключи строки из таблицы, используя rowKeySet метод:

4.8. Получить отчетливый ключ колонки

Мы можем получить все клавиши столбца из таблицы, используя колонкаKeySet метод:

5. Заключение

В этом учебнике мы проиллюстрировали методы Таблица класса из библиотеки Гуавы. Таблица класс предоставляет коллекцию, представляющую таблицу, похожую на структуру, содержащую строки, столбцы и связанные с ними значения ячеев.

Код, относящийся к вышеуказанным примерам, можно найти в проект GitHub – это Maven основе проекта, поэтому она должна быть легко импортировать и работать как есть.

Источник

Gradle: управляя зависимостями

Управление зависимостями – одна из наиболее важных функций в арсенале систем сборки. С приходом Gradle в качестве основной системы сборки Android-проектов в части управления зависимостями произошёл существенный сдвиг, закончилась эпоха ручного копирования JAR-файлов и долгих танцев с бубном вокруг сбоящих конфигураций проекта.

В статье рассматриваются основы управления зависимостями в Gradle, приводятся углублённые практические примеры, небольшие лайфхаки и ссылки на нужные места в документации.

Репозиторий

Как известно, Gradle не имеет собственных репозиториев и в качестве источника зависимостей использует Maven- и Ivy-репозитории. При этом интерфейс для работы с репозиториями не отличается на базовом уровне, более развёрнуто об отличиях параметров вы можете узнать по ссылкам IvyArtifactRepository и MavenArtifactRepository. Стоит отметить, что в качестве url могут использоваться ‘http’, ‘https’ или ‘file’ протоколы. Порядок, в котором записаны репозитории, влияет на порядок поиска зависимости в репозиториях.

Объявление зависимостей

В приведённом выше примере вы видите сценарий сборки, в котором подключены две зависимости для различных конфигураций (compile и testCompile) компиляции проекта. JsonToken будет подключаться во время компиляции проекта и компиляции тестов проекта, jUnit только во время компиляции тестов проекта. Детальнее о конфигурациях компиляции — по ссылке.

Также можно увидеть, что jUnit-зависимость мы подключаем как динамическую(+), т.е. будет использоваться самая последняя из доступных версия 4.+, и нам не нужно будет следить за минорными обновлениями (рекомендую не использовать эту возможность в compile-типе компиляции приложения, т.к. могут появиться неожиданные, возможно, сложно локализуемые проблемы).

На примере с jUnit-зависимостью рассмотрим стандартный механизм Gradle по поиску необходимой зависимости:

В Gradle реализована система кэширования, которая по умолчанию хранит зависимости в течение 24 часов, но это поведение можно переопределить.

После того, как время, установленное для хранения данных в кэше, вышло, система при запуске задач сначала проверит возможность обновления динамических (dynamic) и изменяемых (changing) зависимостей и при необходимости их обновит.

Gradle старается не загружать те файлы, которые были загруженны ранее, и использует для этого систему проверок, даже если URL/источники файлов будут отличаться. Gradle всегда проверяет кэш (URL, версия и имя модуля, кэш других версий Gradle, Maven-кэш), заголовки HTTP-запроса (Date, Content-Length, ETag) и SHA1-хэш, если он доступен. Если совпадений не найдено, то система загрузит файл.

Также в системе сборки присутствуют два параметра, используя которые при запуске вы можете изменить политику кэширования для конкретного выполнения задачи.

Читайте также:  что делать если аккаунт в роблокс заблокировали на 7 дней

– –offline – Gradle никогда не будет пытаться обратиться в сеть для проверки обновлений зависимостей.
– –refresh-dependencies – Gradle попытается обновить все зависимости. Удобно использовать при повреждении данных, находящихся в кэше. Верифицирует кэшированные данные и при отличии обновляет их.

Более детально про кэширование зависимостей можно прочитать в Gradle User Guide.

Виды зависимостей

Существует несколько видов зависимостей в Gradle. Наиболее часто используемыми являются:

– Внешние зависимости проекта — зависимости, загружаемые из внешних репозиториев;

– Проектные зависимости — зависимость от модуля (подпроекта) в рамках одного проекта;

– Файловые зависимости — зависимости, подключаемые как файлы (jar/aar архивы).

Также существуют зависимости клиентских модулей, зависимости Gradle API и локальные Groovy-зависимости. Они используются редко, поэтому в рамках данной статьи не будем их разбирать, но почитать документацию о них можно здесь.

Дерево зависимостей

Каждая внешняя или проектная зависимость может содержать собственные зависимости, которые необходимо учесть и загрузить. Таким образом, при выполнении компиляции происходит загрузка зависимостей для выбранной конфигурации и строится дерево зависимостей, человеческое представление которого можно увидеть, выполнив Gradle task ‘dependencies’ в Android Studio или команду gradle %module_name%:dependencies в консоли, находясь в корневой папке проекта. В ответ вы получите список деревьев зависимостей для каждой из доступных конфигураций.

Используя параметр configuration, указываем имя конфигурации, чтобы видеть дерево зависимостей только указанной конфигурации.

Возьмем специально подготовленные исходники репозитория, расположенного на github и попробуем получить дерево зависимостей для конкретной конфигурации (в данный момент проект находится в состоянии 0, т.е. в качестве build.gradle используется build.gradle.0):

Проанализировав дерево зависимостей, можно увидеть, что модуль app использует в качестве зависимостей две внешних зависимости (appcompat и guava), а также две проектных зависимости (first и second), которые в свою очередь используют библиотеку jsontoken версий 1.0 и 1.1 как внешнюю зависимость. Совершенно очевидно, что проект не может содержать две версии одной библиотеки в Classpath, да и нет в этом необходимости. На этом этапе Gradle включает модуль разрешения конфликтов.

Разрешение конфликтов

Gradle DSL содержит компонент, используемый для разрешения конфликтов зависимостей. Если посмотреть на зависимости библиотеки jsontoken на приведённом выше дереве зависимостей, то мы увидим их только раз. Для модуля second зависимости библиотеки jsontoken не указаны, а вывод самой зависимости содержит дополнительно ‘–> 1.1’, что говорит о том, что версия библиотеки 1.0 не используется, а автоматически была заменена на версию 1.1 с помощью Gradle-модуля разрешения конфликтов.

Для объяснения каким образом была разрешена конфликтная ситуация, также можно воспользоваться Gradle-таском dependencyInsight, например:

Стоит обратить внимание, что версия 1.1 выбирается в результате conflict resolution, также возможен выбор в результате других правил (например: selected by force или selected by rule). В статье будут приведены примеры использования правил, влияющих на стратегию разрешения зависимостей, и выполнив таск dependencyInsight вы сможете увидеть причину выбора конкретной версии библиотеки на каждом из приведённых ниже этапов. Для этого при переходе на каждый этап вы можете самостоятельно выполнить таск dependencyInsight.

При необходимости есть возможность переопределить логику работы Gradle-модуля разрешения конфликтов, например, указав Gradle падать при выявлении конфликтов во время конфигурирования проекта. (состояние 1)

После чего даже при попытке построить дерево зависимостей Gradle таски будут прерываться по причине наличия конфликта в зависимостях приложения.

У задачи есть четыре варианта решения:

Первый вариант – удалить строки, переопределяющие стратегию разрешения конфликтов.

Второй вариант – добавить в стратегию разрешения конфликтов правило обязательного использования библиотеки jsonToken, с указанием конкретной версии (состояние 2):

При применении этого варианта решения дерево зависимостей будет выглядеть следующим образом:

Третий вариант — добавить библиотеку jsonToken явно в качестве зависимости для проекта app и присвоить зависимости параметр force, который явно укажет, какую из версий библиотеки стоит использовать. (состояние 3)

А дерево зависимостей станет выглядеть следующим образом:

Четвёртый вариант – исключить у одной из проектных зависимостей jsontoken из собственных зависимостей с помощью параметра exclude. (состояние 4)

И дерево зависимостей станет выглядеть следующим образом:

Стоит отметить, что exclude не обязательно передавать оба параметра одновременно, можно использовать только один.

Но несмотря на правильный вывод дерева зависимостей, при попытке собрать приложение Gradle вернёт ошибку:

Причину ошибки можно понять из вывода сообщений выполнения задачи сборки — класс GwtCompatible с идентичным именем пакета содержится в нескольких зависимостях. И это действительно так, дело в том, что проект app в качестве зависимости использует библиотеку guava, а библиотека jsontoken использует в зависимостях устаревшую Google Collections. Google Collections входит в Guava, и их совместное использование в одном проекте невозможно.

Добиться успешной сборки проекта можно тремя вариантами:

Первый — удалить guava из зависимостей модуля app. Если используется только та часть Guava, которая содержится в Google Collections, то предложенное решение будет неплохим.

Второй — исключить Google Collections из модуля first. Добиться этого мы можем используя описанное ранее исключение или правила конфигураций. Рассмотрим оба варианта, сначала используя исключения (состояние 5)

Читайте также:  какой знак зодиака у близнецов уизли

Пример использования правил конфигураций (состояние 6):

Дерево зависимостей для обеих реализаций исключения Google Collections будет идентично.

Третий вариант — использовать функционал подмены модулей (состояние 7):

Дерево зависимостей будет выглядеть следующим образом:

Нужно учесть, что если оставить предопределенную логику разрешения конфликтов, которая указывает прерывать сборку при наличии любого конфликта, то выполнение любого таска будет прерываться на этапе конфигурации. Другими словами, использование правил замены модулей является одним из правил стратегии разрешения конфликтов между зависимостями.

Также важно заметить, что последний из озвученных вариантов является самым гибким, ведь при удалении guava из списка зависимостей Gradle, Google Collections сохранится в проекте, и функционал, от него зависящий, сможет продолжить выполнение. А дерево зависимостей будет выглядеть следующим образом:

После каждого из вариантов мы достигнем успеха в виде собранного и запущенного приложения.

Но давайте рассмотрим другую ситуацию (состояние 8), у нас одна единственная сильно урезанная (для уменьшения размеров скриншотов) динамическая зависимость wiremock. Мы её используем сугубо в целях обучения, представьте вместо неё библиотеку, которую поставляет ваш коллега, он может выпустить новую версию в любой момент, и вам непременно необходимо использовать самую последнюю версию:

Дерево зависимостей выглядит следующим образом:

Как вы можете увидеть, Gradle загружает последнюю доступную версию wiremock, которая является beta. Ситуация нормальная для debug сборок, но если мы собираемся предоставить сборку пользователям, то нам определённо необходимо использовать release-версию, чтобы быть уверенными в качестве приложения. Но при этом в связи с постоянной необходимостью использовать последнюю версию и частыми релизами нет возможности отказаться от динамического указания версии wiremock. Решением этой задачи будет написание собственных правил стратегии выбора версий зависимости:

Стоит отменить, что данное правило применится ко всем зависимостям, а не только к wiremock.
После чего, запустив задачу отображения дерева зависимостей в информационном режиме, мы увидим, как отбрасываются beta-версии библиотеки, и причину, по которой они были отброшены. В конечном итоге будет выбрана стабильная версия 1.58:

Но при тестировании было обнаружено, что в версии 1.58 присутствует критичный баг, и сборка не может быть выпущена в таком состоянии. Решить эту задачу можно, написав ещё одно правило выбора версии зависимости:

После чего версия wiremock 1.58 будет также отброшена, и начнёт использоваться версия 1.57, а дерево зависимостей будет выглядеть следующим образом:

Заключение

Несмотря на то, что статья получилась достаточно объемной, тема Dependency Management в Gradle содержит много не озвученной в рамках этой статьи информации. Глубже погрузиться в этот мир лучше всего получится с помощью официального User Guide в паре с документацией по Gradle DSL, в изучение которых придется инвестировать немало времени.

Зато в результате вы получите возможность сэкономить десятки часов, как благодаря автоматизации, так и благодаря пониманию того, что необходимо делать при проявлении различных багов. Например, в последнее время достаточно активно проявляются баги с 65К-методов и Multidex, но благодаря грамотному просмотру зависимостей и использованию exclude проблемы решаются очень быстро.

Источник

Чистый код с Google Guava

Наверное, любому программисту доводилось видеть код, пестрящий большим количеством повторов и реализации «низкоуровневых» действий прямо посреди бизнес-логики. Например, посреди метода, печатающего отчёт, может оказаться такой фрагмент кода, конкатерирующий строки:

Понятно, что этот код мог бы быть более прямолинейным, например, в Java 8 можно написать так:

Вот так сразу гораздо понятнее, что происходит. Google Guava – это набор open-source библиотек для Java, помогающий избавиться от подобных часто встречающихся шаблонов кода. Поскольку Guava появилась задолго до Java 8, в Guava тоже есть способ конкатенации строк: Joiner.on(«, «).join(debtors).

Очень базовые полезности

Давайте рассмотрим простой класс, реализующий стандартный набор базовых методов Java. Предлагаю не вникать особо в реализацию методов hashCode, equals, toString и compareTo (первые три из них я просто сгенерировал в Eclipse) дабы не тратить время впустую, а просто посмотреть на объём кода.

Теперь посмотрим на похожий код, использующий Guava и новые методы из Java 8:

Как видим, код стал чище и лаконичнее. Здесь используются MoreObjects и ComparisonChain из Guava и класс Objects из Java 8. Если вы используете Java 7 или более старую версию, то можете воспользоваться классом Objects из Guava – в нём есть методы hashCode и equal, аналогичные использованным методам hash и equals из класса java.lang.Objects. Раньше toStringHelper тоже находился в классе Objects, но с появлением Java 8 в Guava 18 в классе Objects навесили меточку @Deprecated на все методы, а те методы, аналогов которым которых нет в Java 8, перенесли в MoreObjects, чтобы не было конфликта имён – Guava развивается, а её разработчики не стесняются избавляться от устаревшего кода.

Замечу, что эта версия класса немного отличается от изначальной: я предположил, что отчество может быть не заполнено, в таком случае в результате toString мы его не увидим, а compareTo будет считать, что личности без отчества должны идти после тех, у кого есть отчество (при этом упорядочение происходит сначала по фамили и имени, а только потом по отчеству).

Читайте также:  concha bullosa что это и как лечить

Другим примером весьма базовых полезностей могут служить предусловия. По какой-то причине в Java есть только Objects.requireNotNull (начиная с Java 7).

Кратко о предусловиях:

Имя метода в классе Preconditions Генерируемое исключение
checkArgument(boolean) IllegalArgumentException
checkNotNull(T) NullPointerException
checkState(boolean) IllegalStateException
checkElementIndex(int index, int size) IndexOutOfBoundException
checkPositionIndex(int index,int size) IndexOutOfBoundException

Зачем они нужны, можно прочитать на сайте Oracle.

Новые коллекции

Частенько бывает, что можно увидеть подобного рода код посреди бизнес-логики:

(в последнем отрывке входными данными являются map, key и value). Эти два примера демонстрируют работу с коллекциями, когда в коллекциях содержатся изменяеные данные (в данном случае числа и списки соответственно). В первом случае отображение (map) по-сути описывает мультимножество, т.е. множество с повторяющимися элементами, а во втором случае отображение является мультиотображением. Такие абстракии есть в Guava. Давайте перепишем примеры с использованием этих абстракций:

(здесь map – это Multimap ). Замечу, что Guava позволяет настраивать поведение таких мультиотображений – например, мы можем хотеть, чтобы наборы значений хранились как множества, а можем захотеть списки, для самого же отображения мы можем захотеть связанный список, хэш или дерево – все нужные реализации в Guava имеются. Table – коллекция, избавляющая от аналогичного дублированая кода, но уже на случай хранения отображений внутри отображений. Вот примеры новых коллекций, упрощающих жизнь:

Multiset “Множество”, которое может иметь дубликаты
Multimap “Отображение”, которое может иметь дубликаты
BiMap Поддерживает “обратное отображение”
Table Связывает упорядоченную пару ключей со значением
ClassToInstanceMap Отображает тип на экземпляр этого типа (избавляет от приведений типов)
RangeSet Набор диапазонов
RangeMap Набор отображений непересекающихся диапазонов на ненулевые значения

Декораторы для коллекций

Для создания декораторов к коллекциям – и к тем, что уже есть в Java Collections Framework, и к тем, что определены в Guava – имеются соответствующие классы, например ForwardingList, ForwardingMap, ForwardingMiltiset.

Неизменяемые коллекции

Пара простых примеров:

Реализация итераторов

PeekingIterator Просто оборачивает итератор, добавляя к нему метод peek() для получения значения следующего элемента. Создаётся с помощью вызова Iterators.peekingIterator(Iterator)
AbstractIterator Избавляет от необходимости реализовывать все методы итератора – достаточно только реализовать protected T computeNext()
AbstractSequentialIterator Аналогичен предыдущему, но вычисляет следующий элемент на основе предыдущего: нужно реализовать метод protected T computeNext(T previous)

Функциональные и утилиты для коллекций

Здесь импортированы статические методы из Functions (toStringFunction), Predicates (not, equalTo), Iterables (transform, filter) и FluentIterable (from). В первом случае используются статические методы Iterable, чтобы сконструировать результат, во втором – FluentIterable.

Ввод/вывод

Для абстрагирования байтовых и символьных потоков определены такие абстрактные классы, как ByteSource, ByteSink, CharSoure и CharSink. Создаются они как правило с помощью фасадов Resources и Files. Также имеется немалый набор методов для работы с потоками ввода и вывода, такие как преобразование, считывание, копирование и конкатенация (см. классы CharSource, ByteSource, ByteSink). Примеры:

Обо всём помаленьку

Lists Создание различный видов списков, в т.ч. Lists.newCopyOnWriteArrayList(iterable), Lists.reverse(list) /* view! /, Lists.transform(fromList, function) /* lazy view! */
Sets Преобразование из Map в Set (view!), работа со множествами в математическом смысле (пересечение, объединение, разность)
Iterables Простые методы типа any, all, contains, concat, filter, find, limit, isEmpty, size, toArray, transform. По какой-то причине в Java 8 многие подобные методы относятся только к коллекциям, но не к Iterable в общем.
Bytes, Ints, UnsignedInteger и т.д. Работа с беззнаковыми числами и массивами примитивных типов (соответствующие утилитные классы есть для каждого примитивного типа).
ObjectArrays По-сути только два вида методов – конкатенация массивов (по какой-то причине её нет в стандартной библиотеке Java) и создание массовов по заданному классу или классу массива (почему-то в библиотеке Java есть только аналогичный метод для копирования).
Joiner, Splitter Гибкие классы для объединения или нарезация строк из или в Iterable, List или Map.
Strings, MoreObjects Из неупомянутых – крайне частоиспользуемые методы Strings.emptyToNull(String), Strings.isNullOrEmpty(String), Strings.nullToEmpty(String) и MoreObjects.firstNonNull(T, T)
Closer, Throwables Эмуляция try-with-resources, multi-catch (полезно только для Java 6 и старее), работа с трассировкой стека и перекидывание исключений.
com.google.common.net Названия классов говорят сами за себя: InternetDomainName, InetAddresses, HttpHeaders, MediaType, UrlEscapers
com.google.common.html и com.google.common.xml HtmlEscapers и XmlEscapers
Range Диапазон.
EventBus Мощная реализация паттерна издатель-подписчик. В EventBus регистрируются подписчики, “реагирующие” методы которых помечены аннотацией, а при вызове какого-либо события EventBus находит подписчиков, способных воспринимать данный вид событий, и уведомляет их о событии.
IntMath, LongMath, BigIntegerMath, DoubleMath Множество полезных функций для работы с числами.
ClassPath В Java нет кроссплатформенного способа просматривать классы на classpath. А Guava предоставляет возможность пройтись по классам пакета или проекта.
TypeToken Благодаря стиранию типов мы не можем манипулировать обобщёнными типами во время исполнения программы. TypeToken позволяет манипулировать такими типами.

Ещё примеры

Для создания динамического прокси без Guava обычно пишется такой код:

Источник

Сказочный портал