Некоторые расширенные классы коллекций в Guava

Java

Я написал много статей, связанных с классами коллекций Java, и узнал, как использовать множество классов коллекций. Считаете ли вы, что все еще существуют некоторые общие требования, которым классы коллекций не могут соответствовать? Вам нужно использовать классы в коллекциях Java для реализуйте их самостоятельно, но для нас были построены такие широко используемые колеса Google и apache.

Есть два хорошо известных инструментария, связанных с Java:Google GuavaиApache Commons, Сегодня давайте взглянем на некоторые другие классы коллекций, реализованные в Guava, которые в основном улучшены по сравнению с классами коллекций JDK.

Неизменяемые коллекции -> настоящие неизменяемые коллекции

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

Мы создаем новый список из 5 элементов, затем создаем для него неизменяемый вид.

        List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,5));
        List<Integer> umList = Collections.unmodifiableList(list);

После вышеперечисленных действий мы получилиumList, который неизменен, ноlistне ушел, он все еще изменчив, и мы можем сделать это, давlistдобавить значение для измененияumListнабор элементов.

Так какCollections.unmodifiableList, держитlist, все изменения в списке также будут отражены вumListначальство.

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

использоватьGuavaКак это сделать?


ImmutableCollection li = ImmutableList.of(1, 2, 3, 4, 5);

Ощущается ли это намного яснее, в то же время, этоliдействительно неизменен.

ImmutableList также предоставляет различные методы создания, такие как:

  1. Непосредственно создается с аргументами любого количества элементов.
  2. использоватьcopyOfСоздать из существующего списка
  3. Предоставляет шаблон Builder для цепочки вызовов.

Код выше начинается сImmutableListпример, ноGuavaтакже обеспечиваетImmutableSet,ImmutableMap,ImmutableCollectionи другие классы, которые можно вызывать отдельно в соответствии с требуемой структурой данных.

Другое решение для MultiMap -> Map

У нас часто возникает необходимость хранить список/набор в структуре карты.

Например, чтобы подсчитать дату регистрации пользователя для рисования календаря, нам нужны следующие данные:name->[2019-04-01,2019-04-28]структура данных такая.

Тогда давайте присоединимся к пользователю, чтобы проверить запись о входе в систему 1 мая? Напишите небольшой код,

    // 模拟已有的数据结构
    static Map<String, List<String>> userSign = new HashMap<>();
    // 新放进去一条数据
    public static void putIt(String name, String date) {
	// 正式的逻辑部分
        List<String> dates = userSign.getOrDefault(name, new ArrayList<>());
        if (!dates.contains(date)) {
            dates.add(date);
        }
        userSign.put(name, dates);
    }

Видно, что это более неприятно, и если нет картыgetOrDefault()метода, есть еще несколько строк кода, потому что его приходится делить на существующий и несуществующий..

Guava предоставляет структуру данных для предотвращения ситуации, когда ключ соответствует нескольким значениям, то естьMultiMap.

Хотя его имя носитmap, но глядя на исходный код, можно обнаружить, что его class life не наследует интерфейс Map.

нужно использоватьMultiMapДля реализации вышеуказанного метода, как это:


        ArrayListMultimap<String, String> userSign = ArrayListMultimap.create();
        userSign.put("huyan", "2019-05-01");
        userSign.put("huyan", "2019-05-02");

        List<String> huyanSign = userSign.get("huyan");

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

Скачав исходный код Guava, вы можете обнаружить, что на самом деле он реализован с помощью Map, где он и определен:

2019-05-01-17-15-23

Вы можете видеть, что он определен:Map<K,Collection<V>.определяется какCollectionЭто реализация других централизованных структур данных.

Например:

  • HashMultimapЗначение помещается в набор
  • LinkedListMultimapЗначение помещается в LinkedList.

и Т. Д.

Multiset -> счетчик с именем set

Честно говоря, это очень полезно, но почему это называется набором... У всех впечатление от набора состоит в том, что повторяющиеся элементы нельзя размещать, аMultisetФункция состоит в подсчете повторяющихся элементов.

Он используется следующим образом:


        Multiset<String> s = HashMultiset.create();
        s.add("pf");
        s.add("pf");
        s.add("pf");
        s.add("hh");
	// i =3
        int i = s.count("pf");

Это так же, как счетчик, который я написал несколько дней назад,встречный портал.

Внутренняя реализация использует HashMap для сохраненияkey->countотношение отображения .

BiMap -> значение не может повторяться двунаправленная карта

Этот класс действительно реализует интерфейс карты JDK.Чтобы использовать его, вы должны убедиться, что ни ключ, ни значение не имеют повторяющихся значений.Потому что он поддерживает получение ключа в соответствии со значением, то есть ключ и значение HashMap обмениваются .

        BiMap<String, String> m = HashBiMap.create();

        m.put("pf", "111");

        String value = m.get("pf");
        String key = m.inverse().get("111");

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

Таблица -> Карта > решение

При обнаружении нескольких индексов и одного результатаMap<String,Map<String,Object>>Такая реализация, конечно, возможна, но ее слишком сложно понять и запрограммировать.

Guava предоставляет метод, называемыйTableСтруктура данных может быть реализована элегантно.

Используйте следующим образом:

        Table<Integer, Integer, String> tt = HashBasedTable.create();
        tt.put(1, 2, "huyan");

        String name = tt.get(1, 2);
        Map<Integer, String> row = tt.row(1);
        Map<Integer, String> colum = tt.column(1);
        Set<Table.Cell<Integer, Integer, String>> ha = tt.cellSet();

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

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

Конечно, если вы посмотрите на исходный код, вы обнаружите, что нижний слой таблицы также реализован путем вложения двух карт, но язык Java полностью посвящен инкапсуляции.Хотя мы можем реализовать это сами, нам нужно сделать следующее: изучить его.Метод реализации ,понять,понять и уметь применять аналогичные идеи в других сценариях,вместо того, чтобы каждый раз писать по две карты.Ведь готовые колеса надо использовать больше для углубления своего понимания в применимых сценариях .

ComparisonChain -> Мощный и красивый метод сравнения нескольких полей

В случае сортировки и сравнения нескольких полей наш код обычно уродлив, например следующий класс:

    private static class Student {
        int id;
        String name;
        int age;
    }

У нас нет возможности сравнить или отсортировать его сейчас, потому что для него нет определенной стратегии сравнения, предполагая, что наша стратегия такова:

Первый идентификатор сравнения, идентификатор равен имени сравнения, имя равно значению возраста сравненияЭто очень распространенная многосглавная стратегия сравнения. Итак, мы даемStudentкласс плюсComparableреализация.

	// 为了简洁起见,没有写外部类代码,只贴了重写的comparTo方法.
        @Override
        public int compareTo(Object o) {
            Student s = (Student) o;
            int idResult = s.id - this.id;
            int nameResult = s.name.compareTo(this.name);
            int ageResult = s.age - this.age;

            return idResult != 0 ? idResult : nameResult != 0 ? nameResult : ageResult;
        }

Последняя строка?:?:Не режут ли глаза, конечно можно выбрать тройку если-иначе, не думаю, что сильно лучше.

Но вы можете использоватьComparisonChain, это имя выглядит как цепочка сравнения, что очень подходит для нашей сцены. Перепишем так:

 @Override
        public int compareTo(Object o) {
            Student s = (Student) o;
            return ComparisonChain.start().compare(s.id, this.id).compare(s.name, this.name).compare(s.age, this.age).
                    result();
        }

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

Заказ -> комбинация нескольких компараторов

Приведенная выше ComparisonChain решает ситуацию сортировки нескольких полей при реализации Comparable, поэтому в JDK есть много методов, которым необходимо предоставлять внешние компараторы.Хотим ли мы сейчас сортировать по нескольким компараторам?

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

Ordering<Student> studentOrdering = Ordering.compound(Arrays.asList((o1, o2) -> {
            return ComparisonChain.start().result();
        }, (o1, o2) -> 0, (o1, o2) -> 0));
Collections.sort(students, studentOrdering);

В приведенном выше коде порядок используется для интеграции нескольких компараторов, а затем передается вCollectionsизsortМетод, использующий его для сортировки списка.





ChangeLog

2019-05-01 Завершение

Все вышеизложенное является личными мыслями, если есть какие-либо ошибки, пожалуйста, исправьте их в комментариях.

Добро пожаловать на перепечатку, пожалуйста, подпишите и сохраните исходную ссылку.

Контактный адрес электронной почты: huyanshi2580@gmail.com

Дополнительные заметки об обучении см. в личном блоге ------>Хуян тен