Статьи

Определение присутствия символов или целых чисел в строке с помощью Guava CharMatcher и Apache Commons Lang StringUtils

В недавнем посте Reddit был задан вопрос: « Существует ли предопределенный метод проверки, содержит ли значение переменной определенный символ или целое число? «Этот основанный на вопросе заголовок также задавался по-другому:« Метод или быстрый способ проверки, содержит ли переменная какие-либо числа, скажем или («x», 2, «B») как список? » Я не знаю ни одного вызова метода в стандартных библиотеках SDK для этого (кроме использования тщательно разработанного регулярного выражения), но в этом посте я отвечу на эти вопросы, используя класс CharMatcher Guava и класс StringUtils Apache Common Lang .

Класс String в Java имеет метод содержимого, который можно использовать для определения того, содержится ли в этой String один символ или содержится ли в этой String определенная явно заданная последовательность символов. Тем не менее, я не знаю ни одного способа в одном исполняемом операторе (не считая регулярных выражений) спросить Java, содержит ли данная строка какой-либо из указанного набора символов без необходимости содержать все из них или содержать их в указанном порядке , И Guava, и Apache Commons Lang действительно предоставляют механизмы именно для этого.

Apache Commons Lang ( версия 3.1, используемая в этом посте) предоставляет перегруженные методы StringUtils.containsAny которые легко выполняют этот запрос. Обе перегруженные версии ожидают, что первый переданный им параметр будет String (или, точнее, CharSequence ), чтобы проверить, содержит ли он заданную букву или целое число. Первая перегруженная версия, StringUtils.containsAny (CharSequence, char…), принимает ноль или более элементов char для проверки, чтобы увидеть, есть ли какие-либо из них в строке, представленной первым аргументом. Вторая перегруженная версия, StringUtils.containsAny (CharSequence, CharSequence) ожидает, что второй аргумент будет содержать все потенциальные символы, которые нужно найти в первом аргументе, в виде одной последовательности символов.

В следующем листинге кода показано использование этого подхода Apache Commons Lang для определения, содержит ли данная строка определенные символы. Все три утверждения пройдут свои утверждения, потому что «Вдохновленные фактическими событиями» включают «d» и «A», но не «Q». Поскольку для того, чтобы какой-либо из представленных символов присутствовал, было необходимо только вернуть true, первые два утверждения об истинном проходе. Третье утверждение проходит, потому что строка НЕ ​​содержит единственной предоставленной буквы, и поэтому утверждается отрицательное.

Определение строки содержит символ с помощью StringUtils

1
2
3
4
5
6
private static void demoStringContainingLetterInStringUtils()
{
   assert StringUtils.containsAny("Inspired by Actual Events", 'd', 'A');  // true: both contained
   assert StringUtils.containsAny("Inspired by Actual Events", 'd', 'Q');  // true: one contained
   assert !StringUtils.containsAny("Inspired by Actual Events", 'Q');      // true: none contained (!)
}

CharMatcher Guava также можно использовать аналогичным образом, как показано в следующем листинге кода.

Определение строки содержит символ с CharMatcher

1
2
3
4
5
6
private static void demoStringContainingLetterInGuava()
{
   assert CharMatcher.anyOf("Inspired by Actual Events").matchesAnyOf(new String(new char[]{'d', 'A'}));
   assert CharMatcher.anyOf("Inspired by Actual Events").matchesAnyOf(new String (new char[] {'d', 'Q'}));
   assert !CharMatcher.anyOf("Inspired by Actual Events").matchesAnyOf(new String(new char[]{'Q'}));
}

Что если мы специально хотим убедиться, что хотя бы один символ в заданной последовательности String / CharSequence является числовым (целым числом), но мы не можем гарантировать, что вся строка является числовой? StringUtils можно применить тот же подход, что и выше, с использованием StringUtils Apache Commons Lang. Единственное изменение состоит в том, что сопоставляемым буквам являются цифры от 0 до 9. Это показано на следующем снимке экрана.

Определение строки содержит число с помощью StringUtils

1
2
3
4
5
private static void demoStringContainingNumericDigitInStringUtils()
{
   assert !StringUtils.containsAny("Inspired by Actual Events", "0123456789");
   assert StringUtils.containsAny("Inspired by Actual Events 2013", "0123456789");
}

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

Определение строки содержит число с CharMatcher

1
2
3
4
5
private static void demoStringContainingNumericDigitInGuava()
{
   assert !CharMatcher.DIGIT.matchesAnyOf("Inspired by Actual Events");
   assert CharMatcher.DIGIT.matchesAnyOf("Inspired by Actual Events 2013");
}

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

Для полноты я включил единственный класс, содержащий все приведенные выше примеры, в следующий листинг кода. Функция main() этого класса может быть запущена с флагом -enableassertions (или -ea ), установленным на -ea запуска Java, и завершится без каких-либо -ea AssertionError .

StringContainsDemonstrator.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package dustin.examples.strings;
 
import com.google.common.base.CharMatcher;
import static java.lang.System.out;
 
import org.apache.commons.lang3.StringUtils;
 
/**
 * Demonstrate Apache Commons Lang StringUtils and Guava's CharMatcher. This
 * class exists to demonstrate Apache Commons Lang StringUtils and Guava's
 * CharMatcher support for determining if a particular character or set of
 * characters or integers is contained within a given
 *
 * This class's tests depend on asserts being enabled, so specify the JVM option
 * -enableassertions (-ea) when running this example.
 *
 * @author Dustin
 */
public class StringContainsDemonstrator
{
   private static final String CANDIDATE_STRING = "Inspired by Actual Events";
   private static final String CANDIDATE_STRING_WITH_NUMERAL = CANDIDATE_STRING + " 2013";
   private static final char FIRST_CHARACTER = 'd';
   private static final char SECOND_CHARACTER = 'A';
   private static final String CHARACTERS = new String(new char[]{FIRST_CHARACTER, SECOND_CHARACTER});
   private static final char NOT_CONTAINED_CHARACTER = 'Q';
   private static final String NOT_CONTAINED_CHARACTERS = new String(new char[]{NOT_CONTAINED_CHARACTER});
   private static final String MIXED_CONTAINED_CHARACTERS = new String (new char[] {FIRST_CHARACTER, NOT_CONTAINED_CHARACTER});
   private static final String NUMERIC_CHARACTER_SET = "0123456789";
 
   private static void demoStringContainingLetterInGuava()
   {
      assert CharMatcher.anyOf(CANDIDATE_STRING).matchesAnyOf(CHARACTERS);
      assert CharMatcher.anyOf(CANDIDATE_STRING).matchesAnyOf(MIXED_CONTAINED_CHARACTERS);
      assert !CharMatcher.anyOf(CANDIDATE_STRING).matchesAnyOf(NOT_CONTAINED_CHARACTERS);
   }
 
   private static void demoStringContainingNumericDigitInGuava()
   {
      assert !CharMatcher.DIGIT.matchesAnyOf(CANDIDATE_STRING);
      assert CharMatcher.DIGIT.matchesAnyOf(CANDIDATE_STRING_WITH_NUMERAL);
   }
 
   private static void demoStringContainingLetterInStringUtils()
   {
      assert StringUtils.containsAny(CANDIDATE_STRING, FIRST_CHARACTER, SECOND_CHARACTER);
      assert StringUtils.containsAny(CANDIDATE_STRING, FIRST_CHARACTER, NOT_CONTAINED_CHARACTER);
      assert !StringUtils.containsAny(CANDIDATE_STRING, NOT_CONTAINED_CHARACTER);
   }
 
   private static void demoStringContainingNumericDigitInStringUtils()
   {
      assert !StringUtils.containsAny(CANDIDATE_STRING, NUMERIC_CHARACTER_SET);
      assert StringUtils.containsAny(CANDIDATE_STRING_WITH_NUMERAL, NUMERIC_CHARACTER_SET);
   }
 
   /**
    * Indicate whether assertions are enabled.
    *
    * @return {@code true} if assertions are enabled or {@code false} if
    *    assertions are not enabled (are disabled).
    */
   private static boolean areAssertionsEnabled()
   {
      boolean enabled = false;
      assert enabled = true;
      return enabled;
   }
 
   /**
    * Main function for running methods to demonstrate Apache Commons Lang
    * StringUtils and Guava's CharMatcher support for determining if a particular
    * character or set of characters or integers is contained within a given
    * String.
    *
    * @param args the command line arguments Command line arguments; none expected.
    */
   public static void main(String[] args)
   {
      if (!areAssertionsEnabled())
      {
         out.println("This class cannot demonstrate anything without assertions enabled.");
         out.println("\tPlease re-run with assertions enabled (-ea).");
         System.exit(-1);
      }
 
      out.println("Beginning demonstrations...");
      demoStringContainingLetterInGuava();
      demoStringContainingLetterInStringUtils();
      demoStringContainingNumericDigitInGuava();
      demoStringContainingNumericDigitInStringUtils();
      out.println("...Demonstrations Ended");
   }
}

Guava и Apache Commons Lang очень популярны среди разработчиков Java из-за методов, которые они предоставляют помимо того, что предоставляет SDK, в котором обычно нуждаются разработчики Java. В этой статье я рассмотрел, как можно использовать CharMatcher и Apache Commons Lang от StringUtils для StringUtils но выразительного тестирования, чтобы определить, существует ли какой-либо из набора указанных символов в предоставленной строке.