<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Lobanov Typer</title><generator>teletype.in</generator><description><![CDATA[Lobanov Typer]]></description><image><url>https://img4.teletype.in/files/3d/7d/3d7dd6f0-1c15-42cb-ba66-8e4fcf2f2673.png</url><title>Lobanov Typer</title><link>https://teletype.in/@llax</link></image><link>https://teletype.in/@llax?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=llax</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/llax?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/llax?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sun, 05 Apr 2026 07:20:08 GMT</pubDate><lastBuildDate>Sun, 05 Apr 2026 07:20:08 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@llax/HMG0RNVYQd8</guid><link>https://teletype.in/@llax/HMG0RNVYQd8?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=llax</link><comments>https://teletype.in/@llax/HMG0RNVYQd8?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=llax#comments</comments><dc:creator>llax</dc:creator><title>Абстрактная Фабрика</title><pubDate>Wed, 23 Jul 2025 08:30:03 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/a7/e5/a7e55603-061b-4952-8e8a-a5eae7612f9d.png"></media:content><category>Gof_Patterns</category><tt:hashtag>java</tt:hashtag><tt:hashtag>gof</tt:hashtag><tt:hashtag>patterns</tt:hashtag><description><![CDATA[<img src="https://img1.teletype.in/files/86/06/86068008-7291-4ab3-ac16-41f6b79ff433.png"></img>Абстрактная фабрика — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретные классы.]]></description><content:encoded><![CDATA[
  <tt-tags id="zxDv">
    <tt-tag name="java">#java</tt-tag>
    <tt-tag name="gof">#gof</tt-tag>
    <tt-tag name="patterns">#patterns</tt-tag>
  </tt-tags>
  <p id="QAPZ"><strong>Абстрактная фабрика</strong> — это порождающий паттерн проектирования, который предоставляет интерфейс для создания семейств взаимосвязанных или взаимозависимых объектов, не специфицируя их конкретные классы.</p>
  <p id="cuet">Паттерн решает проблему создания объектов, когда система должна быть независима от процесса их генерации, композиции и представления. Он используется, когда клиентскому коду необходимо работать с несколькими семействами продуктов, но при этом он не должен зависеть от конкретных классов этих продуктов.</p>
  <p id="5HAs">Для этого <u>создаётся абстрактный класс-фабрика</u> с набором абстрактных методов для создания каждого продукта в семействе. <u>Затем</u> для каждой вариации семейства реализуется <u>конкретная фабрика</u>, которая возвращает определённые, но гарантированно совместимые между собой, экземпляры продуктов. Клиентский код оперирует только интерфейсами (абстрактной фабрики и абстрактных продуктов), что позволяет легко заменять целые семейства объектов, просто подставляя другую реализацию фабрики.</p>
  <hr />
  <h3 id="TmbK">Другими словами</h3>
  <p id="rYPH">Представьте, что вы пришли в IKEA. Вам нужен не просто стол, а полный комплект мебели для комнаты: стол, стул, шкаф и кровать. Главное — чтобы всё сочеталось по стилю.</p>
  <p id="PUo1">Вы можете бегать по всему магазину и пытаться подобрать предметы по отдельности, рискуя ошибиться (например, взять стул в стиле хай-тек к столу в стиле прованс). А можете просто выбрать одну мебельную серию, например, «ХЕМНЭС». В этой серии все предметы уже созданы так, чтобы идеально подходить друг другу по цвету, материалу и дизайну.</p>
  <p id="wtXZ"><strong>Абстрактная фабрика — это и есть этот «каталог серий» в мире программирования.</strong></p>
  <p id="oQoh">Вы выбираете одну «серию» (например, ФабрикаСтиляАр-деко), и она поставляет вам полный, гарантированно совместимый набор объектов (креслоАр-деко, диванАр-деко, столикАр-деко). Вам не нужно думать о деталях — только выбрать нужный стиль. А если захотите сменить его на «Модерн», вы просто возьмёте другой «каталог» (ФабрикуСтиляМодерн), не меняя свой основной код.</p>
  <h2 id="d0mP">Проблема</h2>
  <p id="yTXV">Представьте, что мы пишем симулятор выживания в мире после апокалипсиса. Важная часть игры — постройка убежищ. Код содержит:</p>
  <ol id="rIe1">
    <li id="y8AN"><strong>Семейство зависимых компонентов.</strong> Скажем, любое убежище состоит из Стены + Дверь + Источник питания.</li>
    <li id="QOcV"><strong>Несколько вариаций этого семейства.</strong> Например, компоненты Стены, Дверь и Источник питания могут быть собраны в разных стилях, в зависимости от доступных ресурсов и технологий: Хлам-тек (из подручных материалов), Военный (из армейских компонентов) и Высокотехнологичный (из довоенных научных разработок).</li>
  </ol>
  <p id="LDGn">Вам нужно, чтобы компоненты убежища были совместимы друг с другом. Это важно, потому что выжившие не смогут установить бронированную дверь военного образца в хлипкую стену из металлолома. Несоответствие технологий может привести к катастрофе.</p>
  <p id="I1ju">Кроме того, вы не хотите переписывать основной код игры каждый раз, когда добавляете новый тип убежищ или их компоненты. В мире игры могут найтись чертежи для постройки, например, Био-убежища, и вы бы не хотели менять существующую логику строительства при добавлении новых возможностей.</p>
  <h3 id="NMoZ">Решение</h3>
  <p id="Z7Eh">Для начала паттерн Абстрактная фабрика предлагает выделить общие интерфейсы для отдельных компонентов, составляющих убежище. Так, все вариации стен получат общий интерфейс Стена, все двери реализуют интерфейс Дверь и так далее.</p>
  <p id="Qbuj">Далее вы создаёте абстрактную фабрику убежищ — общий интерфейс, который содержит методы создания всех компонентов семейства (например, создатьСтену, создатьДверь и создатьИсточникПитания). Эти операции должны возвращать <strong>абстрактные</strong> типы компонентов, представленные интерфейсами, которые мы выделили ранее — Стена, Дверь и ИсточникПитания.</p>
  <p id="P3GY">Как насчёт вариаций убежищ? Для каждой вариации (стиля) мы должны создать свою собственную фабрику, реализовав абстрактный интерфейс. Фабрики создают компоненты одной вариации. Например, ФабрикаВоенногоБункера будет возвращать только ЖелезобетонныеСтены, БронированнуюДверь и ДизельныйГенератор. Таким образом, клиентский код, отвечающий за постройку, получает фабрику и использует её для создания совместимых частей, не вникая в детали их реализации.</p>
  <h3 id="V15z">Пример</h3>
  <p id="GlS4">Для примера, предположим, что мы создаём убежища двух типов: из подручных материалов (Хлам-тек) и укрепленный военный бункер. Каждый тип убежища требует своих стен, двери и источника питания.</p>
  <pre id="HMSn" data-lang="java">// Интерфейс для стен убежища
interface Wall {
    void getDescription();
}

// Интерфейс для двери
interface Door {
    void getDescription();
}

// Интерфейс для источника питания
interface PowerSource {
    void getDescription();
}</pre>
  <p id="XIdB">Теперь создадим конкретные реализации компонентов для убежища в стиле Хлам-тек:</p>
  <pre id="YOqz" data-lang="java">// Стена из металлолома
class ScrapWall implements Wall {
    @Override
    public void getDescription() {
        System.out.println(&quot;Стена, собранная из ржавого листового металла и мусора.&quot;);
    }
}

// Дверь из досок и арматуры
class ScrapDoor implements Door {
    @Override
    public void getDescription() {
        System.out.println(&quot;Дверь, сколоченная из досок и укрепленная арматурой.&quot;);
    }
}

// Генератор из старого автомобильного двигателя
class CarEngineGenerator implements PowerSource {
    @Override
    public void getDescription() {
        System.out.println(&quot;Источник питания: шумный генератор на базе автомобильного двигателя.&quot;);
    }
}</pre>
  <p id="XuA5">Теперь создадим аналогичные реализации для Военного бункера:</p>
  <pre id="Htmd" data-lang="java">// Железобетонная стена
class ReinforcedConcreteWall implements Wall {
    @Override
    public void getDescription() {
        System.out.println(&quot;Стена из армированного железобетона, выдержит небольшой взрыв.&quot;);
    }
}

// Бронированная дверь-шлюз
class BlastDoor implements Door {
    @Override
    public void getDescription() {
        System.out.println(&quot;Герметичная бронированная дверь-шлюз.&quot;);
    }
}

// Военный дизельный генератор
class MilitaryDieselGenerator implements PowerSource {
    @Override
    public void getDescription() {
        System.out.println(&quot;Источник питания: надежный и мощный военный дизельный генератор.&quot;);
    }
}</pre>
  <p id="JaYf">Теперь определим интерфейс абстрактной фабрики, которая будет создавать наборы компонентов:</p>
  <pre id="1LmP" data-lang="java">// Интерфейс абстрактной фабрики убежищ
interface ShelterFactory {
    Wall createWall();
    Door createDoor();
    PowerSource createPowerSource();
}</pre>
  <p id="6zar">И, наконец, создадим конкретные фабрики для каждого типа убежища:</p>
  <pre id="EkdY" data-lang="java">// Фабрика для создания убежища из хлама
class ScrapShelterFactory implements ShelterFactory {
    @Override
    public Wall createWall() {
        return new ScrapWall();
    }

    @Override
    public Door createDoor() {
        return new ScrapDoor();
    }

    @Override
    public PowerSource createPowerSource() {
        return new CarEngineGenerator();
    }
}

// Фабрика для создания военного бункера
class MilitaryBunkerFactory implements ShelterFactory {
    @Override
    public Wall createWall() {
        return new ReinforcedConcreteWall();
    }

    @Override
    public Door createDoor() {
        return new BlastDoor();
    }

    @Override
    public PowerSource createPowerSource() {
        return new MilitaryDieselGenerator();
    }
}</pre>
  <p id="D4Bw">Теперь код, отвечающий за строительство, может получить нужную фабрику (например, на основе найденных чертежей) и построить цельное, совместимое убежище, не зная, из каких именно деталей оно состоит.</p>
  <h3 id="AtHD">Шаги реализации</h3>
  <ol id="M60s">
    <li id="LBl0">Создайте таблицу соотношений типов продуктов к вариациям семейств продуктов.</li>
    <li id="B4fv">Сведите все вариации продуктов к общим интерфейсам.</li>
    <li id="Jq7Q">Определите интерфейс абстрактной фабрики. Он должен иметь фабричные методы для создания каждого из типов продуктов.</li>
    <li id="Y3DU">Создайте классы конкретных фабрик, реализовав интерфейс абстрактной фабрики. Этих классов должно быть столько же, сколько и вариаций семейств продуктов.</li>
    <li id="pazn">Измените код инициализации программы так, чтобы она создавала определённую фабрику и передавала её в клиентский код.</li>
    <li id="CY0o">Замените в клиентском коде участки создания продуктов через конструктор вызовами соответствующих методов фабрики.</li>
  </ol>
  <h2 id="nyYx">Вопросы</h2>
  <p id="mqIm"><strong>1. В чем разница между Абстрактной фабрикой и Фабричным методом?</strong></p>
  <p id="RxQn"><strong>Фабричный метод</strong> — это один метод для создания <strong>одного</strong> объекта. Решение о том, какой класс создавать, делегируется подклассам (наследование).</p>
  <p id="pLHW"><strong>Абстрактная фабрика</strong> — это интерфейс для создания <strong>семейства</strong> взаимосвязанных объектов. Использует композицию: клиентский код работает с объектом фабрики.</p>
  <p id="BcSj"><strong>Аналогия:</strong> Фабричный метод — это станок, производящий один тип детали (гвозди). Абстрактная фабрика — это целый завод (например, «Ивановский мебельный завод»), который производит всё для комплекта мебели (столы, стулья, шкафы).</p>
  <ol id="5WYA">
    <ul id="ZAiI">
      <ul id="VuyR"></ul>
    </ul>
  </ol>
  <p id="ubcl"><strong>2. В чем разница между Абстрактной фабрикой и Строителем (Builder)?</strong></p>
  <p id="fGwG"><strong>Абстрактная фабрика</strong> фокусируется на создании <strong>семейства объектов</strong>. Продукты создаются и возвращаются сразу.</p>
  <p id="0rep"><strong>Строитель</strong> фокусируется на пошаговом создании <strong>одного сложного объекта</strong>. Продукт возвращается только в конце, после вызова метода build().</p>
  <p id="QWUE"><strong>Пример:</strong> Абстрактная фабрика создаст вам сразу Двигатель, Кузов и Колеса для автомобиля Ford, в зависимости от выбранной реализации/семейства. Строитель будет по шагам собирать один сложный объект Дом, вызывая методы добавитьПотолок(), добавитьПол(), добавитьСтены(); вы можете выбирать части из разных семейств, постепенно создавая свой дом мечты </p>
  <p id="UIuA"><strong>3. Назовите главный недостаток Абстрактной фабрики</strong></p>
  <p id="Wbne">Главный недостаток — <strong>сложность добавления нового типа продукта</strong>. Если вы захотите добавить в семейство Лампу (к Креслу, Дивану, Столику), вам придётся изменить интерфейс Абстрактной Фабрики, а затем — все её конкретные реализации (ФабрикаАр-деко, ФабрикаМодерн и т.д.).</p>
  <h2 id="xDc5">Задача</h2>
  <p id="XY2Z">«Представьте, что у нас есть код, который напрямую создает объекты: new WindowsButton(), new WindowsCheckbox(). Проведите рефакторинг этого кода с использованием паттерна Абстрактная фабрика».</p>
  <ul id="wavF">
    <li id="yODN">Создать интерфейсы Button, Checkbox.</li>
    <li id="OBd5">Создать интерфейс GUIFactory с методами createButton() и createCheckbox().</li>
    <li id="UBX5">Создать классы WindowsButton, WindowsCheckbox и WindowsFactory.</li>
    <li id="qIKP">Создать классы MacButton, MacCheckbox и MacFactory.</li>
    <li id="FfoN">В клиентском коде заменить new WindowsButton() на factory.createButton().</li>
  </ul>
  <ol id="BkEo">
    <ul id="jYev">
      <ol id="alLr"></ol>
    </ul>
    <ul id="vuez">
      <ul id="WhMB"></ul>
    </ul>
  </ol>
  <h2 id="PlKu">Ресурсы</h2>
  <p id="9WFM"><a href="https://refactoringguru.cn/ru/design-patterns/abstract-factory" target="_blank">Абстрактная фабрика</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@llax/rxzOiofXNRX</guid><link>https://teletype.in/@llax/rxzOiofXNRX?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=llax</link><comments>https://teletype.in/@llax/rxzOiofXNRX?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=llax#comments</comments><dc:creator>llax</dc:creator><title>Расширяем возможности Java с Google Guava: дополнительные коллекции, примеры использования</title><pubDate>Mon, 05 Aug 2024 09:40:28 GMT</pubDate><category>Java Core</category><description><![CDATA[Google Guava — это библиотека для Java, разработанная Google, которая предоставляет множество удобных утилит для работы с коллекциями, функциональным программированием, кэшированием, параллелизмом и другими аспектами разработки. В этой статье мы рассмотрим дополнительные реализации коллекций, предлагаемые Google Guava, приведем примеры их использования и покажем, как добавить библиотеку в проект.]]></description><content:encoded><![CDATA[
  <h2 id="jN4e">Введение</h2>
  <p id="LeCW">Google Guava — это библиотека для Java, разработанная Google, которая предоставляет множество удобных утилит для работы с коллекциями, функциональным программированием, кэшированием, параллелизмом и другими аспектами разработки. В этой статье мы рассмотрим дополнительные реализации коллекций, предлагаемые Google Guava, приведем примеры их использования и покажем, как добавить библиотеку в проект.</p>
  <h2 id="4E0U">Установка Google Guava в проект</h2>
  <p id="fm6m">Для использования Google Guava в проекте необходимо добавить зависимость в файл конфигурации сборки. Инструкции для разных систем сборки можно найти на <a href="https://github.com/google/guava" target="_blank">официальной странице Google Guava на GitHub</a>.</p>
  <h3 id="H6ws">Использование с Maven</h3>
  <p id="Kg5d">Добавьте следующую зависимость в ваш <code>pom.xml</code>:</p>
  <pre id="3wkN" data-lang="css">&lt;dependency&gt;
  &lt;groupId&gt;com.google.guava&lt;/groupId&gt;
  &lt;artifactId&gt;guava&lt;/artifactId&gt;
  &lt;version&gt;32.1.2-jre&lt;/version&gt;
&lt;/dependency&gt;</pre>
  <h3 id="2own">Использование с Gradle</h3>
  <p id="NySA">Добавьте следующую строку в ваш файл <code>build.gradle</code>:</p>
  <pre id="h1ua" data-lang="graphql">implementation &#x27;com.google.guava:guava:32.1.2-jre&#x27;</pre>
  <h2 id="3YmA">Основные Коллекции Google Guava</h2>
  <p id="sDo8">Guava предоставляет несколько расширений стандартных коллекций Java, а также новые типы коллекций, которые упрощают и улучшают работу с данными. Вот некоторые из них:</p>
  <h3 id="qQU9">Immutable Collections</h3>
  <p id="VLHK">Неизменяемые коллекции гарантируют, что их содержимое не будет изменяться после создания. Это делает их потокобезопасными и может улучшить производительность, устраняя необходимость синхронизации.</p>
  <p id="XYJI"><strong>Пример использования:</strong></p>
  <pre id="5OuS" data-lang="java">import com.google.common.collect.ImmutableList;

public class ImmutableExample {
    public static void main(String[] args) {
        ImmutableList&lt;String&gt; immutableList = ImmutableList.of(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;);
        System.out.println(immutableList);
        
        // Any attempt to modify the list will throw UnsupportedOperationException
        // immutableList.add(&quot;four&quot;); // This will throw an exception
    }
}</pre>
  <h3 id="Wf5p">Multiset</h3>
  <p id="CmvH">Multiset — это коллекция, которая позволяет хранить дубликаты элементов и отслеживать количество их вхождений.</p>
  <p id="O2jA"><strong>Пример использования:</strong></p>
  <pre id="W96N" data-lang="java">import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;

public class MultisetExample {
    public static void main(String[] args) {
        Multiset&lt;String&gt; multiset = HashMultiset.create();
        multiset.add(&quot;apple&quot;);
        multiset.add(&quot;banana&quot;);
        multiset.add(&quot;apple&quot;);
        
        System.out.println(multiset.count(&quot;apple&quot;)); // Output: 2
        System.out.println(multiset.count(&quot;banana&quot;)); // Output: 1
        
    }
}</pre>
  <h3 id="9Pzw">Multimap</h3>
  <p id="JI9C">Multimap — это коллекция, которая позволяет хранить несколько значений для одного ключа.</p>
  <p id="VBda"><strong>Пример использования:</strong></p>
  <pre id="OKe0" data-lang="java">import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

public class MultimapExample {
    public static void main(String[] args) {
        Multimap&lt;String, String&gt; multimap = ArrayListMultimap.create();
        multimap.put(&quot;fruit&quot;, &quot;apple&quot;);
        multimap.put(&quot;fruit&quot;, &quot;banana&quot;);
        multimap.put(&quot;vegetable&quot;, &quot;carrot&quot;);
        
        System.out.println(multimap.get(&quot;fruit&quot;)); // Output: [apple, banana]
        System.out.println(multimap.get(&quot;vegetable&quot;)); // Output: [carrot]
    }
}
</pre>
  <h3 id="ehlQ">BiMap</h3>
  <p id="kwCm">BiMap — это двухсторонняя карта, которая позволяет уникальные соответствия между ключами и значениями. Это означает, что вы можете выполнять обратный поиск по значениям, как и по ключам.</p>
  <p id="yQgB"><strong>Пример использования:</strong></p>
  <pre id="X8QN" data-lang="java">import com.google.common.collect.HashBiMap;
import com.google.common.collect.BiMap;

public class BiMapExample {
    public static void main(String[] args) {
        BiMap&lt;String, Integer&gt; biMap = HashBiMap.create();
        biMap.put(&quot;one&quot;, 1);
        biMap.put(&quot;two&quot;, 2);
        
        System.out.println(biMap.get(&quot;one&quot;)); // Output: 1
        System.out.println(biMap.inverse().get(1)); // Output: one
    }
}
</pre>
  <h3 id="EZfM">Table</h3>
  <p id="qqIq">Table представляет собой двумерную карту, аналогичную Map&lt;R, Map&lt;C, V&gt;&gt;.</p>
  <p id="Qfio"><strong>Пример использования:</strong></p>
  <pre id="4kqI" data-lang="java">import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

public class TableExample {
    public static void main(String[] args) {
        Table&lt;String, String, Integer&gt; table = HashBasedTable.create();
        table.put(&quot;row1&quot;, &quot;col1&quot;, 1);
        table.put(&quot;row1&quot;, &quot;col2&quot;, 2);
        table.put(&quot;row2&quot;, &quot;col1&quot;, 3);
        
        System.out.println(table.get(&quot;row1&quot;, &quot;col1&quot;)); // Output: 1
        System.out.println(table.row(&quot;row1&quot;)); // Output: {col1=1, col2=2}
        System.out.println(table.column(&quot;col1&quot;)); // Output: {row1=1, row2=3}
    }
}
</pre>
  <h3 id="4N2v">RangeSet и RangeMap</h3>
  <p id="V0wQ">RangeSet и RangeMap предоставляют удобные способы работы с диапазонами чисел и ассоциациями диапазонов с объектами.</p>
  <p id="yg88"><strong>Пример использования RangeSet:</strong></p>
  <pre id="xE4W" data-lang="java">import com.google.common.collect.Range;
import com.google.common.collect.TreeRangeSet;
import com.google.common.collect.RangeSet;

public class RangeSetExample {
    public static void main(String[] args) {
        RangeSet&lt;Integer&gt; rangeSet = TreeRangeSet.create();
        rangeSet.add(Range.closed(1, 10));
        rangeSet.add(Range.closed(20, 30));
        
        System.out.println(rangeSet.contains(5)); // Output: true
        System.out.println(rangeSet.contains(15)); // Output: false
    }
}
</pre>
  <p id="dLW1">Пример использования RangeMap:</p>
  <pre id="fT4s" data-lang="java">import com.google.common.collect.Range;
import com.google.common.collect.TreeRangeMap;
import com.google.common.collect.RangeMap;

public class RangeMapExample {
    public static void main(String[] args) {
        RangeMap&lt;Integer, String&gt; rangeMap = TreeRangeMap.create();
        rangeMap.put(Range.closed(1, 10), &quot;Low&quot;);
        rangeMap.put(Range.closed(11, 20), &quot;Medium&quot;);
        
        System.out.println(rangeMap.get(5)); // Output: Low
        System.out.println(rangeMap.get(15)); // Output: Medium
    }
}
</pre>
  <h2 id="2VcA">Заключение</h2>
  <p id="tJln">Google Guava предоставляет множество дополнительных коллекций, которые значительно расширяют возможности стандартных коллекций Java. Использование этих коллекций может упростить разработку, повысить производительность и улучшить читаемость кода. В этой статье мы рассмотрели основные из них, включая неизменяемые коллекции, Multiset, Multimap, BiMap, Table, RangeSet и RangeMap, и привели примеры их использования. Изучение и использование этих коллекций поможет вам создавать более эффективные и надежные приложения на Java.</p>
  <p id="uRAy">Google Guava делает вашу работу с коллекциями более выразительной и удобной, предоставляя множество дополнительных инструментов и возможностей. Попробуйте использовать эти коллекции в своих проектах и убедитесь в их преимуществах сами.</p>

]]></content:encoded></item></channel></rss>