Статьи

Мультикарты — Google Guava

Это первая из серии публикаций, в которых я попытаюсь объяснить и изучить потрясающую библиотеку Java на языке гуавы от Google .

Я впервые наткнулся на Гуаву, когда искал универсальные версии коллекций Apache Commons — мне был нужен Bimap, и мне надоело перетаскивать свой код с помощью забросов — однако то, что я обнаружил, было намного лучше.

Мало того, что он содержит различные реализации более сложных (но полезные) типов коллекций — Multimaps , мультинаборы , Bimaps — что я буду обсуждать в деталях, но и средства для поддержки более функционального стиля программирования с неизменными коллекциями, а также функцию и предикатобъекты. Это полностью изменило то, как я пишу Java, и в то же время заставило меня все больше расстраиваться из-за неуклюжего синтаксиса Java, что я собираюсь исследовать в следующих статьях.

Во всяком случае, достаточно с введением и с хорошим материалом. Первое, на что я хотел бы взглянуть, это Multimap, которая, вероятно, является единственной функцией Guava, которую я использовал чаще всего.

Mutlimaps

Итак, как часто вам нужна структура данных, как показано ниже?

Map<String,List<MyClass>> myClassListMap test2
                              = new HashMap<String,List<MyClass>>()

Если вы похожи на меня, довольно часто. И разве вы не пишете один и тот же шаблонный код снова и снова?

Чтобы поместить пару ключ / значение в эту карту, необходимо сначала проверить, существует ли список для вашего ключа, и не создает ли он его. Вы закончите тем, что написали что-то вроде следующего:

void putMyObject(String key, Object value) {
    List<Object> myClassList = myClassListMap.get(key);
    if(myClassList == null) {
        myClassList = new ArrayList<object>();
        myClassListMap.put(key,myClassList);
    }
    myClassList.add(value);
}

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

Никогда не бойся Гуава здесь!

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

Таким образом, используя мультикарту, мы могли бы заменить объявление структуры данных следующим:

Multimap<String,Object> myMultimap = ArrayListMultimap.create();

Здесь есть несколько вещей, на которые стоит обратить внимание. Объявление универсального типа должно выглядеть очень знакомым, именно так вы бы объявили карту нормалей.

Возможно, вы ожидали увидеть новый ArrayListMultimap <String, Object> () в правой части равенства. Что ж, все реализации коллекций Guava предлагают метод create, который обычно более лаконичен и имеет то преимущество, что вам не нужно дублировать информацию общего типа.

Guava фактически добавляет аналогичные функциональные возможности к стандартным коллекциям Java Например, если вы изучите com.google.common.collect.Lists , вы увидите статические методы newArrayList () и newLinkedList (), так что вы можете воспользоваться этой краткостью даже со стандартными коллекциями Java. (Я постараюсь рассказать об этом более подробно в следующем посте).

Итак, мы объявили и создали экземпляр мультикарты, как нам их использовать? Легко, как обычная карта!

public class MutliMapTest {
    public static void main(String... args) {
  Multimap<String, String> myMultimap = ArrayListMultimap.create();
   
  // Adding some key/value
  myMultimap.put("Fruits", "Bannana");
  myMultimap.put("Fruits", "Apple");
  myMultimap.put("Fruits", "Pear");
  myMultimap.put("Vegetables", "Carrot");
   
  // Getting the size
  int size = myMultimap.size();
  System.out.println(size);  // 4
   
  // Getting values
  Collection<string> fruits = myMultimap.get("Fruits");
  System.out.println(fruits); // [Bannana, Apple, Pear]
   
  Collection<string> vegetables = myMultimap.get("Vegetables");
  System.out.println(vegetables); // [Carrot]
   
  // Iterating over entire Mutlimap
  for(String value : myMultimap.values()) {
   System.out.println(value);
  }
   
  // Removing a single value
  myMultimap.remove("Fruits","Pear");
  System.out.println(myMultimap.get("Fruits")); // [Bannana, Pear]
   
  // Remove all values for a key
  myMultimap.removeAll("Fruits");
  System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
 }
}

Вам может быть интересно узнать, почему метод get возвращает Collection, а не List, что было бы гораздо более полезным. Это действительно так. Проблема в том, что существует несколько различных реализаций, некоторые используют списки — ArrayListMultimap, LinkedListMultimap и т. Д. — а некоторые используют наборы — HashMultimap, TreeMultimap и другие.

Чтобы справиться с этим — если вам нужно работать непосредственно со списками или наборами на карте, — определено несколько подынтерфейсов. ListMultimap, SetMultimap и SortedSetMultimap. Все они делают то, что вы ожидаете, и их методы, которые возвращают коллекции, возвращают один из подходящих типов.

т.е.

ListMutlimap<String,String> myMutlimap = ArrayListMultimap.create();
 
List<string> myValues = myMutlimap.get("myKey");  // Returns a List, not a Collection.

Это в основном все, что есть для них. Я рекомендую взглянуть на API: http://docs.guava-libraries.googlecode.com/git-history/release09/javadoc/com/google/common/collect/Multimap.html , где вы можете найти различные реализации, вы должен быть в состоянии найти тот, который соответствует вашим потребностям.

Итак, пока что все. В моем следующем посте я буду представлять BiMap