Статьи

Коллекции Guava2: фильтрация и трансформация коллекций Java

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

Класс Collections2 в Guava содержит два открытых метода, оба из которых являются статическими. Методы filter (Collection, Predicate) и transform (Collection, Function) делают то, что подразумевают их имена: выполняют фильтрацию и преобразование соответственно для данной коллекции. Коллекция, подлежащая фильтрации или преобразованию, является первым параметром для каждого статического метода. Второй аргумент фильтрующей функции — это экземпляр класса Predicate в Guava. Второй аргумент функции преобразования — это экземпляр класса Function Гуавы. Оставшаяся часть этого поста демонстрирует объединение всего этого для фильтрации и преобразования коллекций Java.

Фильтрация коллекций с помощью Guava

Фильтрация коллекций с помощью Guava довольно проста. Следующий фрагмент кода демонстрирует простой пример этого. Предоставляется Set String (не показанный во фрагменте кода, но очевидный в выходных данных, следующих за кодом), и этот предоставленный Set фильтруется только для записей, начинающихся с заглавной буквы «J». Это делается с помощью поддержки регулярных выражений Java и Predicates.containsPattern (String) в Guava, но есть и другие типы предикатов, которые можно указывать.

Фильтрация строк, начинающихся с ‘J’

01
02
03
04
05
06
07
08
09
10
11
12
13
14
/**
 * Demonstrate Guava's Collections2.filter method. Filter String beginning
 * with letter 'J'.
 */
public static void demonstrateFilter()
{
   printHeader('Collections2.filter(Collection,Predicate): 'J' Languages');
   final Set<String> strings = buildSetStrings();
   out.println('\nOriginal Strings (pre-filter):\n\t' + strings);
   final Collection<String> filteredStrings =
           Collections2.filter(strings, Predicates.containsPattern('^J'));
   out.println('\nFiltered Strings:\n\t' + filteredStrings);
   out.println('\nOriginal Strings (post-filter):\n\t' + strings);
}

Результат выполнения вышеуказанного метода показан ниже. Эти выходные данные показывают длинный список языков программирования, которые составляют исходный Set String возвращаемых buildSetStrings() и показывают результаты вызова фильтра, показывающие только те языки программирования, которые начинаются с ‘J.’

Преобразование коллекций с гуавой

Преобразование коллекций с помощью Guava работает аналогично синтаксической фильтрации, но Function используется для указания того, как записи исходной коллекции «преобразуются» в выходную коллекцию, а не с помощью Predicate чтобы определить, какие записи следует сохранить. Следующий фрагмент кода демонстрирует преобразование записей в данной коллекции в их верхнюю версию.

Преобразование записей в верхний регистр

01
02
03
04
05
06
07
08
09
10
11
12
13
14
/**
 * Demonstrate Guava's Collections2.transform method. Transform input
 * collection's entries to uppercase form.
 */
public static void demonstrateTransform()
{
   printHeader('Collections2.transform(Collection,Function): Uppercase');
   final Set<String> strings = buildSetStrings();
   out.println('\nOriginal Strings (pre-transform):\n\t' + strings);
   final Collection<String> transformedStrings =
           Collections2.transform(strings, new UpperCaseFunction<String, String>());
   out.println('\nTransformed Strings:\n\t' + transformedStrings);
   out.println('\nOriginal Strings (post-transform):\n\t' + strings);
}

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

UpperCaseFunction.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package dustin.examples;
 
import com.google.common.base.Function;
 
/**
 * Simple Guava Function that converts provided object's toString() representation
 * to upper case.
 *
 * @author Dustin
 */
public class UpperCaseFunction<F, T> implements Function<F, T>
{
   @Override
   public Object apply(Object f)
   {
      return f.toString().toUpperCase();
   }
}

Результат запуска фрагмента кода преобразования, использующего класс UpperCaseFunction показан далее.

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

GuavaCollections2.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
package dustin.examples;
 
import static java.lang.System.out;
 
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
 
/**
 * Class whose sole reason for existence is to demonstrate Guava's Collections2
 * class.
 *
 * @author Dustin
 */
public class GuavaCollections2
{
   /**
    * Provides a Set of Strings.
    *
    * @return Set of strings representing some programming languages.
    */
   private static Set<String> buildSetStrings()
   {
      final Set<String> strings = new HashSet<String>();
      strings.add('Java');
      strings.add('Groovy');
      strings.add('Jython');
      strings.add('JRuby');
      strings.add('Python');
      strings.add('Ruby');
      strings.add('Perl');
      strings.add('C');
      strings.add('C++');
      strings.add('C#');
      strings.add('Pascal');
      strings.add('Fortran');
      strings.add('Cobol');
      strings.add('Scala');
      strings.add('Clojure');
      strings.add('Basic');
      strings.add('PHP');
      strings.add('Flex/ActionScript');
      strings.add('JOVIAL');
      return strings;
   }
 
   /**
    * Demonstrate Guava's Collections2.filter method. Filter String beginning
    * with letter 'J'.
    */
   public static void demonstrateFilter()
   {
      printHeader('Collections2.filter(Collection,Predicate): 'J' Languages');
      final Set<String> strings = buildSetStrings();
      out.println('\nOriginal Strings (pre-filter):\n\t' + strings);
      final Collection<String> filteredStrings =
              Collections2.filter(strings, Predicates.containsPattern('^J'));
      out.println('\nFiltered Strings:\n\t' + filteredStrings);
      out.println('\nOriginal Strings (post-filter):\n\t' + strings);
   }
 
   /**
    * Demonstrate Guava's Collections2.transform method. Transform input
    * collection's entries to uppercase form.
    */
   public static void demonstrateTransform()
   {
      printHeader('Collections2.transform(Collection,Function): Uppercase');
      final Set<String> strings = buildSetStrings();
      out.println('\nOriginal Strings (pre-transform):\n\t' + strings);
      final Collection<String> transformedStrings =
              Collections2.transform(strings, new UpperCaseFunction<String, String>());
      out.println('\nTransformed Strings:\n\t' + transformedStrings);
      out.println('\nOriginal Strings (post-transform):\n\t' + strings);
   }
 
   /**
    * Print a separation header including the provided text.
    *
    * @param headerText Text to be included in separation header.
    */
   private static void printHeader(final String headerText)
   {
      out.println('\n==========================================================');
      out.println('== ' + headerText);
      out.println('==========================================================');
   }
 
   /**
    * Main function for demonstrating Guava's Collections2 class.
    *
    * @param arguments
    */
   public static void main(final String[] arguments)
   {
      demonstrateFilter();
      demonstrateTransform();
   }
}

Прежде чем завершить этот пост, следует обратить внимание на один важный момент. Оба метода, определенные в классе Collections2 содержат предупреждения в документации Javadoc об их использовании. Оба метода предоставляют коллекции, которые считаются «живыми представлениями» исходных коллекций и, таким образом, «изменения одного влияют на другой». Например, удаление элемента из исходной коллекции аналогичным образом удаляет его из преобразованной коллекции. Документация для каждого метода также предупреждает, что ни одна из них не возвращает коллекцию, которая является сериализуемой или поточно-ориентированной, даже если исходная коллекция была сериализуемой и / или поточно-ориентированной.

Вывод

Guava упрощает фильтрацию коллекций и преобразование записей коллекций в Java. Хотя этот код может быть не таким лаконичным, как в Groovy, для создания похожих вещей, он лучше, чем написание простого Java-кода без использования класса Collections2 в Guava. Коллекции Java могут быть отфильтрованы с помощью Collections2.filter(Collection,Predicate) или преобразованы с помощью Collections2.transform(Collection,Function) .

Ссылка: Фильтрация и преобразование коллекций Java с коллекциями Guava2 от нашего партнера JCG Дастина Маркса в блоге Inspired by Actual Events .