В Javadoc для класса ChoiceFormat говорится, что ChoiceFormat «позволяет вам присоединять формат к диапазону чисел» и «обычно используется в MessageFormat для обработки множественного числа». Этот пост описывает java.text.ChoiceFormat и предоставляет несколько примеров его применения в коде Java.
Одно из наиболее заметных отличий между ChoiceFormat и другими классами « format » в пакете 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[] и описывается как «limit в возрастающем порядке». Второй параметр массива называется «format», имеет тип String[] и описывается как «соответствующие строки формата». Согласно Javadoc, этот конструктор «конструирует с ограничениями и соответствующими форматами».
Использование конструктора ChoiceFormat принимающего два аргумента массива, продемонстрировано в следующем листинге кода (метод writeGradeInformation(ChoiceFormat) и переменная fredsTestScores будут показаны позже).
|
01
02
03
04
05
06
07
08
09
10
11
12
|
/** * 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 на основе двух массивов для «форматирования» предоставленных числовых значений в виде строк. Реализация метода показана далее.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/** * 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 использованное в этих примерах.
|
01
02
03
04
05
06
07
08
09
10
|
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 с двумя массивами, приводит к следующему выводу:
|
1
2
3
4
5
|
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 созданный в предыдущем примере с конструктором, который принимает два массива.
|
01
02
03
04
05
06
07
08
09
10
|
/** * 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.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
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 , вывод будет таким, как показано ниже.
|
01
02
03
04
05
06
07
08
09
10
|
-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. Это можно сделать, как показано в следующем листинге кода.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
/** * 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);} |
Когда вышеуказанный метод выполняется, его вывод показывает, что оба подхода обеспечивают соблюдение граничных условий лучше.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
-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 основе ChoiceFormat в качестве нижнего предела этого недопустимого диапазона используется число, немного превышающее 100. Экземпляр ChoiceFormat основе строковых / шаблонных ChoiceFormat обеспечивает большую гибкость и точность при указании нижнего предела диапазона «Недопустимый — слишком высокий» для любого числа больше 100,0 с использованием символа «меньше» (<).
Обработка None, Singular и Plural с помощью ChoiceFormat
Я открыл этот пост, процитировав Javadoc, заявив, что ChoiceFormat «обычно используется в MessageFormat для обработки множественного числа», но еще не продемонстрировал это общее использование в этом посте. Я продемонстрирую часть этого (множественное число без MessageFormat ) очень кратко здесь для полноты, но гораздо более полное объяснение (множественное число с MessageFormat ) этого распространенного использования ChoiceFormat доступно в уроке Обработка множественных ChoiceFormat в Учебниках Java (часть Интернационализации). след ).
Следующий листинг кода демонстрирует применение ChoiceFormat для обработки единственного и множественного числа.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
/** * 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) + "."); }} |
Выполнение примера в последнем листинге кода приводит к выводу, который показан далее.
|
01
02
03
04
05
06
07
08
09
10
11
|
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 синтаксический анализ шаблона ChoiceFormat для форматирования строк из сгенерированного числового значения, является \u2264 ( ≤ ). Это продемонстрировано в следующем листинге кода и выводе этого кода, который следует за листингом кода. Обратите внимание, что в этом примере \u2264 работает так же, как и при использовании более простого знака # показанного ранее.
|
01
02
03
04
05
06
07
08
09
10
11
|
/** * 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);} |
|
1
2
3
4
5
|
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 сделанные в ходе этого поста, и его примеры.
- При использовании конструктора ChoiceFormat (double [], String []) два переданных массива должны иметь одинаковый размер, иначе будет выброшено исключение IllegalArgumentException («Массив и лимитный массив должны иметь одинаковую длину.»).
- Массив « limit »
double[]предоставляемый конструктору ChoiceFormat (double [], String []), должен иметь пределы, перечисленные слева направо в порядке возрастания чисел. Если это не так, исключение не выдается, но логика почти наверняка не будет правильной, поскольку строки, отформатированные для экземпляраChoiceFormatбудут «совпадать» неправильно. То же самое ожидание относится к конструктору, принимающему шаблон. -
ChoiceFormatпозволяет использовать Double.POSITIVE_INFINITY и Double.NEGATIVE_INFINITY для указания нижних пределов диапазона с помощью конструктора из двух массивов. -
ChoiceFormatпозволяет использовать\u221Eи-\u221Eдля указания нижних пределов диапазона с помощью своего единственного конструктора String (pattern). - Конструктор
ChoiceFormatпринимающий шаблон String, немного более гибок, чем конструктор с двумя массивами, и позволяет задавать границы нижнего предела как все в пределах определенного количества, не включая это определенное количество точно. - Символы и символы со специальным значением в шаблонах String, предоставляемых одному конструктору String
ChoiceFormatвключают#,<,\u2264(≤),\u221E(∞) и|,
Вывод
ChoiceFormat позволяет настраивать числовые диапазоны так, чтобы определенные диапазоны могли иметь разные и конкретные представления. Этот пост охватывал несколько различных аспектов форматирования числовых диапазонов с помощью ChoiceFormat , но анализ числовых диапазонов из строк с использованием ChoiceFormat в этом посте не рассматривался.
Дальнейшее чтение
- Документация API ChoiceFormat
- Обработка множественного числа
- Текст: Свобода с форматом сообщения. Часть 2. Выбор формата
- Плюрализация Java i18n с использованием ChoiceFormat
- Что не так с ChoiceFormat? (Затерянный в переводе — часть IV)
- Подробнее о том, что не так с ChoiceFormat
| Ссылка: | ChoiceFormat: форматирование числового диапазона от нашего партнера JCG Дастина Маркса в блоге Inspired by Actual Events . |