choiceformat
ChoiceFormat类的Javadoc指出ChoiceFormat
“允许您将格式附加到一系列数字上”,并且“通常在MessageFormat中用于处理复数”。 这篇文章描述了java.text.ChoiceFormat
并提供了一些在Java代码中应用它的示例。
ChoiceFormat
与java.text包中其他“ 格式 ”类之间最明显的区别之一是ChoiceFormat
不提供用于访问ChoiceFormat
实例的静态方法。 相反, ChoiceFormat
提供了两个用于实例化ChoiceFormat
对象的构造函数。 用于ChoiceFormat
的Javadoc重点说明了这一点:
ChoiceFormat
与其他Format
类的不同之处在于,您使用构造函数(而不是使用getInstance样式工厂方法)创建ChoiceFormat
对象。 不需要工厂方法,因为ChoiceFormat
不需要为给定语言环境进行任何复杂的设置。 实际上,ChoiceFormat
不会实现任何特定ChoiceFormat
语言环境的行为。
用两个数组构造ChoiceFormat
ChoiceFormat
提供的两个构造函数中的第一个接受两个数组作为其参数。 第一个数组是原始双精度数组,表示每个间隔的最小值(起始值)。 第二个数组是一个字符串数组,代表与每个时间间隔关联的名称。 这两个数组必须具有相同数量的元素,因为在数字(双)间隔和描述这些间隔的字符串之间存在假定的一对一映射。 如果两个数组的元素数量不同,则会遇到以下异常。
线程“主”中的异常java.lang.IllegalArgumentException:数组和限制数组的长度必须相同。
ChoiceFormat(double [],String [])构造函数的Javadoc说明第一个数组参数名为“ limits”,类型为double[]
,并被描述为“升序限制”。 第二个数组参数名为“ formats”,类型为String[]
,并被描述为“相应的格式字符串”。 根据Javadoc,此构造函数“以限制和相应的格式进行构造”。
下一个代码清单中演示了使用ChoiceFormat
构造函数接受两个数组参数的writeGradeInformation(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
实例来“格式化”测试成绩。 “格式”不是打印数字值,而是打印与数字值所在的时间间隔关联的字符串。 下一个代码清单显示了这些示例中使用的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
接受基于String的模式的ChoiceFormat(String)
构造函数可能对那些愿意使用具有类似格式化类的基于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
构造函数中设置的“限制”是“包含的”,这意味着这些限制适用于指定的限制和更高的限制(直到下一个限制)。 换句话说,数字范围被定义为大于或等于指定的限制。 ChoiceFormat
的Javadoc文档使用数学描述对此进行了描述:
当且仅当limit [j]≤X <limit [j + 1]时,X与j匹配
边界测试分数示例的输出还演示了Javadoc文档中描述的ChoiceFormat
另一个特征:“如果不匹配,则使用第一个或最后一个索引,具体取决于数字(X)太低还是太低”高。” 因为在提供的ChoiceFormat
实例中不存在-25.0的匹配项,所以将最低范围(最低限度为“ F”)应用于低于最低范围的那个数字。 在这些测试成绩示例中,没有为“ A”指定比“ 90”更高的限制,因此所有高于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的任何数字时,提供了更大的灵活性和准确性。
使用ChoiceFormat处理无,单数和复数
我通过引用Javadoc来打开这篇文章,指出ChoiceFormat
是“通常在MessageFormat中用于处理复数形式”,但尚未在本文中演示这种常用用法。 为了完整起见 ,我将在此处非常简短地演示其中的一部分(没有MessageFormat的复数),但是Java教程的 “ 处理复数”课 ( 国际化的一部分)中提供了ChoiceFormat
的这种常用用法的更完整的说明(带有MessageFormat的复数)。 径 )。
下一个代码清单演示了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模式支持的最后一个符号
\u2264
( ≤
)是ChoiceFormat
模式分析可识别的另一种符号,用于根据生成的数值格式化字符串。 在下一个代码清单以及该代码清单之后的代码输出中对此进行了演示。 请注意,在此示例中, \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 (“ Array和limit数组必须具有相同的长度。”)。
- 提供给ChoiceFormat(double [],String [])构造函数的“ limits”
double[]
数组应具有从左到右以数字升序排列的限制。 如果不是这种情况,则不会引发任何异常,但是逻辑几乎肯定不会正确,因为针对ChoiceFormat
实例进行格式化的字符串将错误地“匹配”。 同样的期望也适用于接受模式的构造函数。 -
ChoiceFormat
允许Double.POSITIVE_INFINITY和Double.NEGATIVE_INFINITY通过其两个数组的构造函数用于指定范围下限。 -
ChoiceFormat
允许\u221E
和-\u221E
通过其单个String(模式)构造函数来指定较低的范围限制。 -
ChoiceFormat
构造函数接受String模式比双数组构造函数灵活一些,并且允许将下限边界指定为一定数量范围内的所有内容,而不必确切地包含该特定数量。 - 提供给单个String
ChoiceFormat
构造函数的String模式中具有特殊含义的符号和字符包括#
,<
,\u2264
(≤
),\u221E
(∞
)和|
。
结论
ChoiceFormat允许自定义数字范围的格式,以便特定范围可以具有不同和特定的表示形式。 这篇文章涵盖了使用ChoiceFormat
进行数字范围格式化的几个不同方面,但是这篇文章中没有涉及使用ChoiceFormat
从字符串中解析数字范围 。
进一步阅读
- ChoiceFormat API文档
- 处理复数
- 文本:消息格式的自由–第2部分:选择格式
- 使用ChoiceFormat的Java i18n多元化
- ChoiceFormat有什么问题? (翻译后的内容–第四部分)
- 进一步了解ChoiceFormat的问题
翻译自: https://www.javacodegeeks.com/2014/09/choiceformat-numeric-range-formatting.html
choiceformat