Статьи

ChoiceFormat: форматирование числового диапазона

Javadoc для класса ChoiceFormat  состояний , что  ChoiceFormat «позволяет присоединить формат к диапазону чисел» и «обычно используется в MessageFormat для обработки множественном.» Этот пост описывает  java.text.ChoiceFormat и предоставляет несколько примеров применения его в коде Java.

Одно из наиболее заметных отличий между  ChoiceFormat другими « форматными » классами в  пакете java.text заключается в том, что  ChoiceFormat они не предоставляют статические методы для доступа к экземплярам  ChoiceFormat. Вместо этого  ChoiceFormat предоставляет два конструктора, которые используются для создания  ChoiceFormat объектов. Javadoc для  ChoiceFormat основных моментов и объясняет это:

ChoiceFormat отличается от других 
Format классов тем, что вы создаете 
ChoiceFormatобъект с помощью конструктора (не с помощью метода фабрики стилей getInstance). Методы фабрики не нужны, потому 
ChoiceFormat что не требуют какой-либо сложной настройки для данной локали. Фактически, 
ChoiceFormat не реализует никакого поведения, специфичного для локали.

Построение формата выбора с двумя массивами

Первый из двух предоставленных конструкторов  ChoiceFormat принимает в качестве аргументов два массива. Первый массив — это массив примитивных двойников, которые представляют наименьшее значение (начальное значение) каждого интервала. Второй массив — это массив строк, которые представляют имена, связанные с каждым интервалом. Два массива должны иметь одинаковое количество элементов, поскольку между числовыми (двойными) интервалами и строками, описывающими эти интервалы, предполагается однозначное сопоставление. Если два массива не имеют одинаковое количество элементов, возникает следующее исключение.


Исключение в потоке «main» java.lang.IllegalArgumentException: Массивы и лимиты должны иметь одинаковую длину.

Javadoc для конструктора  ChoiceFormat (double [], String [])  утверждает, что первый параметр массива называется «limit», имеет тип  double[]и описывается как «пределы в порядке возрастания». Второй параметр массива называется «форматы», имеет тип  String[]и описывается как «соответствующие строки формата». Согласно Javadoc, этот конструктор «конструирует с ограничениями и соответствующими форматами».

Использование  ChoiceFormat конструктора, принимающего два аргумента массива, продемонстрировано в следующем листинге кода (  writeGradeInformation(ChoiceFormat) метод и  fredsTestScores переменная будут показаны позже).

/**
 * Demonstrate ChoiceFormat instantiated with ChoiceFormat
 * constructor that accepts an array of double and an array
 * of String.
 */
public void demonstrateChoiceFormatWithDoublesAndStringsArrays()
{
   final double[] minimumPercentages = {0, 60, 70, 80, 90};
   final String[] letterGrades = {"F", "D", "C", "B", "A"};
   final ChoiceFormat gradesFormat = new ChoiceFormat(minimumPercentages, letterGrades);
   writeGradeInformation(fredsTestScores, gradesFormat);
}

Приведенный выше пример соответствует ожиданиям проиллюстрированного  ChoiceFormat конструктора. Два массива имеют одинаковое количество элементов, первый double[]массив ( ) имеет свои элементы в порядке возрастания, а второй ( String[]) массив имеет свои «форматы» в том же порядке, что и соответствующие пределы начала интервала в первом массиве.

writeGradeInformation(ChoiceFormat) Метод , указанный в фрагменте кода выше демонстрирует использование  , ChoiceFormat например на основе двух массивов в «формат» при условии , числовые значения в виде строк. Реализация метода показана далее.

/**
 * Write grade information to standard output
 * using the provided ChoiceFormat instance.
 *
 * @param testScores Test Scores to be displayed with formatting.
 * @param gradesFormat ChoiceFormat instance to be used to format output.
 */
public void writeGradeInformation(
   final Collection<Double> testScores,
   final ChoiceFormat gradesFormat)
{
   double sum = 0;
   for (final Double testScore : testScores)
   {
      sum += testScore;
      out.println(testScore + " is a '" + gradesFormat.format(testScore) + "'.");
   }
   double average = sum / testScores.size();
   out.println(
        "The average score (" + average + ") is a '"
      + gradesFormat.format(average) + "'.");
}

Приведенный выше код использует  ChoiceFormat экземпляр, предоставленный для «форматирования» результатов тестов. Вместо печати числового значения «format» печатает строку, связанную с интервалом, в который попадает числовое значение. Следующий листинг кода показывает определение  fredsTestScores используемых в этих примерах.

private static List<Double> fredsTestScores;
static
{
   final ArrayList<Double> scores = new ArrayList<>();
   scores.add(75.6);
   scores.add(88.8);
   scores.add(97.3);
   scores.add(43.3);
   fredsTestScores = Collections.unmodifiableList(scores);
}

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

75.6 is a 'C'.
88.8 is a 'B'.
97.3 is a 'A'.
43.3 is a 'F'.
The average score (76.25) is a 'C'.

Построение ChoiceFormat со строкой шаблона

ChoiceFormat(String) Конструктор , который принимает строку на основе шаблона может быть более привлекательным для разработчиков , которые удобно использовать строки на основе шаблона с аналогичными классами форматирования , таких как DateFormat  и  DecimalFormat . Следующий листинг кода демонстрирует использование этого конструктора. Шаблон, предоставленный конструктору, приводит к тому, что экземпляр  ChoiceFormat должен форматироваться так же, как ChoiceFormat экземпляр, созданный в предыдущем примере, с конструктором, который принимает два массива.

/**
 * Demonstrate ChoiceFormat instantiated with ChoiceFormat
 * constructor that accepts a String pattern.
 */
public void demonstrateChoiceFormatWithStringPattern()
{
   final String limitFormatPattern = "0#F | 60#D | 70#C | 80#B | 90#A";
   final ChoiceFormat gradesFormat = new ChoiceFormat(limitFormatPattern);
   writeGradeInformation(fredsTestScores, gradesFormat);
}

writeGradeInformation Метод , называемый здесь такой же , как тот , называемый ранее и выход также тот же (не показан здесь , потому что это то же самое).

ChoiceFormat Поведение на крайностях и границах

До сих пор примеры хорошо работали с результатами тестов в ожидаемых диапазонах. Еще один набор результатов тестов теперь будет использоваться для демонстрации некоторых других особенностей  ChoiceFormat. Этот новый набор тестовых оценок настроен в следующем листинге кода и включает в себя «невозможный» отрицательный балл и другой «вероятный невозможный» балл выше 100.

private static List<Double> boundaryTestScores;
static
{
   final ArrayList<Double> boundaryScores = new ArrayList<Double>();
   boundaryScores.add(-25.0);
   boundaryScores.add(0.0);
   boundaryScores.add(20.0);
   boundaryScores.add(60.0);
   boundaryScores.add(70.0);
   boundaryScores.add(80.0);
   boundaryScores.add(90.0);
   boundaryScores.add(100.0);
   boundaryScores.add(115.0);
   boundaryTestScores = boundaryScores;
}

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

-25.0 is a 'F '.
0.0 is a 'F '.
20.0 is a 'F '.
60.0 is a 'D '.
70.0 is a 'C '.
80.0 is a 'B '.
90.0 is a 'A'.
100.0 is a 'A'.
115.0 is a 'A'.
The average score (56.666666666666664) is a 'F '.

Только что показанный вывод демонстрирует, что «пределы», установленные в  ChoiceFormat конструкторах, являются «включающими», что означает, что эти ограничения применяются к указанному пределу и выше (до следующего предела). Другими словами, диапазон числа определяется как больше или равно указанному пределу. Документация Javadoc для ChoiceFormat описывает это с математическим описанием:


X соответствует j тогда и только тогда, когда limit [j] ≤ X <limit [j + 1]

Выходные данные из примера результатов тестов границ также демонстрируют другую характеристику, ChoiceFormat описанную в документации Javadoc: «Если совпадений нет, то используется либо первый, либо последний индекс, в зависимости от того, слишком мало или слишком много число (X) «. Поскольку в предоставленных ChoiceFormat экземплярах нет совпадения для -25.0  , самый низкий («F» для предела 0) диапазон применяется к этому числу ниже, чем самый низкий диапазон. В этих примерах теста не указан более высокий предел, чем «90» для «A», поэтому все оценки выше 90 (включая оценки выше 100) относятся к «A». Давайте предположим, что мы хотели, чтобы диапазоны оценок были от 0 до 100, иначе форматированный результат должен указывать «Неверно» для оценок меньше 0 или больше 100.Это можно сделать, как показано в следующем листинге кода.

/**
 * Demonstrating enforcing of lower and upper boundaries
 * with ChoiceFormat instances.
 */
public void demonstrateChoiceFormatBoundariesEnforced()
{
   // Demonstrating boundary enforcement with ChoiceFormat(double[], String[])
   final double[] minimumPercentages = {Double.NEGATIVE_INFINITY, 0, 60, 70, 80, 90, 100.000001};
   final String[] letterGrades = {"Invalid - Too Low", "F", "D", "C", "B", "A", "Invalid - Too High"};
   final ChoiceFormat gradesFormat = new ChoiceFormat(minimumPercentages, letterGrades);
   writeGradeInformation(boundaryTestScores, gradesFormat);

   // Demonstrating boundary enforcement with ChoiceFormat(String)
   final String limitFormatPattern = "-\u221E#Invalid - Too Low | 0#F | 60#D | 70#C | 80#B | 90#A | 100.0<Invalid - Too High";
   final ChoiceFormat gradesFormat2 = new ChoiceFormat(limitFormatPattern);
   writeGradeInformation(boundaryTestScores, gradesFormat2);
}

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

-25.0 is a 'Invalid - Too Low'.
0.0 is a 'F'.
20.0 is a 'F'.
60.0 is a 'D'.
70.0 is a 'C'.
80.0 is a 'B'.
90.0 is a 'A'.
100.0 is a 'A'.
115.0 is a 'Invalid - Too High'.
The average score (56.666666666666664) is a 'F'.
-25.0 is a 'Invalid - Too Low '.
0.0 is a 'F '.
20.0 is a 'F '.
60.0 is a 'D '.
70.0 is a 'C '.
80.0 is a 'B '.
90.0 is a 'A '.
100.0 is a 'A '.
115.0 is a 'Invalid - Too High'.
The average score (56.666666666666664) is a 'F '.

В последнем листинге кода показано использование  Double.NEGATIVE_INFINITY  и  \u221E ( символ Unicode INFINITY ) для установления максимально возможной границы предела в каждом из примеров. Чтобы значения выше 100.0 были отформатированы как недопустимые, для массивов  ChoiceFormat используется число, немного большее 100, в качестве нижнего предела этого недопустимого диапазона. ChoiceFormat Экземпляр на основе строки / шаблона  обеспечивает большую гибкость и точность при указании нижнего предела диапазона «Недопустимый — слишком высокий» для любого числа больше 100,0 с использованием символа «меньше» (<).

Обработка None, Singular и Plural с помощью ChoiceFormat

Я открыл этот пост, процитировав Javadoc, в котором говорится, что  ChoiceFormat «он обычно используется в MessageFormat для обработки множественного числа», но еще не продемонстрировал это общее использование в этом посте. Я продемонстрирую часть этого (множественном без  MessageFormat ) очень кратко здесь для полноты картины , но гораздо более полное объяснение (множественном с  MessageFormat ) этого общего пользования  ChoiceFormat предоставляется в  Java Tutorials »  Обработка множественного числа уроков  (часть  тропы Интернационализация ).

Следующий листинг кода демонстрирует применение  ChoiceFormat для обработки единственного и множественного числа.

/**
 * Demonstrate ChoiceFormat used for differentiation of
 * singular from plural and none.
 */
public void demonstratePluralAndSingular()
{
   final double[] cactiLowerLimits = {0, 1, 2, 3, 4, 10};
   final String[] cactiRangeDescriptions =
      {"no cacti", "a cactus", "a couple cacti", "a few cacti", "many cacti", "a plethora of cacti"};
   final ChoiceFormat cactiFormat = new ChoiceFormat(cactiLowerLimits, cactiRangeDescriptions);
   for (int cactiCount = 0; cactiCount < 11; cactiCount++)
   {
      out.println(cactiCount + ": I own " + cactiFormat.format(cactiCount) + ".");
   }
}

Запуск примера в последнем листинге кода приводит к выводу, который показан далее.

0: I own no cacti.
1: I own a cactus.
2: I own a couple cacti.
3: I own a few cacti.
4: I own many cacti.
5: I own many cacti.
6: I own many cacti.
7: I own many cacti.
8: I own many cacti.
9: I own many cacti.
10: I own a plethora of cacti.

Один последний символ, поддерживаемый шаблоном ChoiceFormat

Другим символом, который  ChoiceFormat распознает синтаксический анализ шаблона для форматирования строк из сгенерированного числового значения, является  \u2264 ( ). Это продемонстрировано в следующем листинге кода и выводе этого кода, который следует за листингом кода. Обратите внимание, что в этом примере работа  \u2264 работает так же, как при использовании более простого  # знака, показанного ранее.

/**
 * Demonstrate using \u2264 in String pattern for ChoiceFormat
 * to represent >= sign. Treated differently than less-than
 * sign but similarly to #.
 */
public void demonstrateLessThanOrEquals()
{
   final String limitFormatPattern = "0\u2264F | 60\u2264D | 70\u2264C | 80\u2264B | 90\u2264A";
   final ChoiceFormat gradesFormat = new ChoiceFormat(limitFormatPattern);
   writeGradeInformation(fredsTestScores, gradesFormat);
}
75.6 is a 'C '.
88.8 is a 'B '.
97.3 is a 'A'.
43.3 is a 'F '.
The average score (76.25) is a 'C '.

Наблюдения в обзоре

В этом разделе я кратко излагаю некоторые замечания,  ChoiceFormat сделанные в ходе этого поста, и его примеры.

  • При использовании конструктора  ChoiceFormat (double [], String []) два переданных массива должны иметь одинаковый размер, иначе   будет выброшено исключение IllegalArgumentException («Массив и лимитный массив должны иметь одинаковую длину.»).
  • double[] Массив « limit »,  предоставляемый конструктору  ChoiceFormat (double [], String []), должен иметь пределы, перечисленные слева направо в порядке возрастания номеров. Когда это не так, исключение не выдается, но логика почти наверняка не будет правильной, поскольку строки, отформатированные для экземпляра,  ChoiceFormat будут «совпадать» неправильно. То же самое ожидание относится к конструктору, принимающему шаблон.
  • ChoiceFormat позволяет использовать  Double.POSITIVE_INFINITY  и  Double.NEGATIVE_INFINITY  для указания нижних пределов диапазона с помощью конструктора из двух массивов.
  • ChoiceFormat позволяет  \u221E и  -\u221E может быть использован для определения нижних пределов диапазона с помощью единственного конструктора String (pattern).
  • ChoiceFormat Конструктор принимающего шаблона Строки является немного более гибким , чем конструктор два массивов и позволяет указать нижние предельные границы , как все за определенную сумму без учета , что определенное количество раз.
  • Символы и знаки с особым значением в моделях Струнные , предоставленных одной Струнный ChoiceFormat конструктора включают в себя  #<\u2264 ( ),  \u221E ( ), и  |.

Вывод

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

Дальнейшее чтение