# Class ChoiceFormat

java.lang.Object
java.text.Format
java.text.NumberFormat
java.text.ChoiceFormat

All Implemented Interfaces:
  `Serializable, Cloneable`

public class ChoiceFormat extends NumberFormat
`ChoiceFormat` is a concrete subclass of `NumberFormat` that allows you to attach a format to a range of numbers. It is generally used in a `MessageFormat` for handling plurals. The choice is specified with an ascending list of doubles, where each item specifies a half-open interval up to the next item:

>     X matches j if and only if limit[j] ≤ X < limit[j+1]

If there is no match, then either the first or last index is used, depending on whether the number (X) is too low or too high. If the limit array is not in ascending order, the results of formatting will be incorrect. ChoiceFormat also accepts `\u221E` as equivalent to infinity(INF).

Note: `ChoiceFormat` differs from the other `Format` classes in that you create a `ChoiceFormat` object with a constructor (not with a `getInstance` style factory method). The factory methods aren't necessary because `ChoiceFormat` doesn't require any complex setup for a given locale. In fact, `ChoiceFormat` doesn't implement any locale specific behavior.

## Patterns

A `ChoiceFormat` pattern has the following syntax:

> Pattern:
>   SubPattern *("|" SubPattern)
> SubPattern:
>   Limit Relation Format
>   Note: Each additional SubPattern must have an ascending Limit-Relation interval
> Limit:
>   Number / "∞" / "-∞"
> Number:
>   ["-"] *(Digit) 1*(Decimal / Digit) *(Digit) [Exponent]
> Decimal:
>   1*(Digit ".") / 1*("." Digit)
> Digit:
>   0 - 9
> Exponent:
>   *(Digit) Digit ExponentSymbol Digit *(Digit)
> ExponentSymbol:
>   "e" / "E"
> Relation:
>   "#" / "<" / "≤"
> Format:
>   Any characters except the special pattern character '|'

Note:The relation ≤ is not equivalent to <=

To use a reserved special pattern character within a Format pattern, it must be single quoted. For example, `new ChoiceFormat("1#'|'foo'|'").format(1)` returns `"|foo|"`. Use two single quotes in a row to produce a literal single quote. For example, `new ChoiceFormat("1# ''one'' ").format(1)` returns `" 'one' "`.

## Usage Information

A `ChoiceFormat` can be constructed using either an array of formats and an array of limits or a string pattern. When constructing with format and limit arrays, the length of these arrays must be the same. For example,

- limits = {1,2,3,4,5,6,7}
  formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}
- limits = {0, 1, ChoiceFormat.nextDouble(1)}
  formats = {"no files", "one file", "many files"}
  (`nextDouble` can be used to get the next higher double, to make the half-open interval.)

Below is an example of constructing a ChoiceFormat with arrays to format and parse values:

    double[] limits = {1,2,3,4,5,6,7};
    String[] dayOfWeekNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
    ChoiceFormat form = new ChoiceFormat(limits, dayOfWeekNames);
    ParsePosition status = new ParsePosition(0);
    for (double i = 0.0; i <= 8.0; ++i) {
        status.setIndex(0);
        System.out.println(i + " -> " + form.format(i) + " -> "
                                 + form.parse(form.format(i),status));
    }

Below is an example of constructing a ChoiceFormat with a String pattern:

    ChoiceFormat fmt = new ChoiceFormat(
         "-1#is negative| 0#is zero or fraction | 1#is one |1.0<is 1+ |2#is two |2<is more than 2.");

    System.out.println(fmt.format(Double.NEGATIVE_INFINITY)); // outputs "is negative"
    System.out.println(fmt.format(-1.0)); // outputs "is negative"
    System.out.println(fmt.format(0)); // outputs "is zero or fraction"
    System.out.println(fmt.format(0.9)); // outputs "is zero or fraction"
    System.out.println(fmt.format(1)); // outputs "is one"
    System.out.println(fmt.format(1.5)); // outputs "is 1+"
    System.out.println(fmt.format(2)); // outputs "is two"
    System.out.println(fmt.format(2.1)); // outputs "is more than 2."
    System.out.println(fmt.format(Double.NaN)); // outputs "is negative"
    System.out.println(fmt.format(Double.POSITIVE_INFINITY)); // outputs "is more than 2."

For more sophisticated patterns, `ChoiceFormat` can be used with `MessageFormat` to produce accurate forms for singular and plural:

    MessageFormat msgFmt = new MessageFormat("The disk \"{0}\" contains {1}.");
    double[] fileLimits = {0,1,2};
    String[] filePart = {"no files","one file","{1,number} files"};
    ChoiceFormat fileChoices = new ChoiceFormat(fileLimits, filePart);
    msgFmt.setFormatByArgumentIndex(1, fileChoices);
    Object[] args = {"MyDisk", 1273};
    System.out.println(msgFmt.format(args));

The output with different values for `fileCount`:

>     The disk "MyDisk" contains no files.
>     The disk "MyDisk" contains one file.
>     The disk "MyDisk" contains 1,273 files.

See `MessageFormat` for caveats regarding `MessageFormat` patterns within a `ChoiceFormat` pattern.

## Synchronization

Choice formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

API Note:
  A subclass could perform more consistent pattern validation by throwing an `IllegalArgumentException` for all incorrect cases. See the `Implementation Note` for this implementation's behavior regarding incorrect patterns.

  This class inherits instance methods from `NumberFormat` it does not utilize; a subclass could override and throw `UnsupportedOperationException` for such methods.

Implementation Note:
  Given an incorrect pattern, this implementation may either throw an exception or succeed and discard the incorrect portion. A `NumberFormatException` is thrown if a `limit` can not be parsed as a numeric value and an `IllegalArgumentException` is thrown if a `SubPattern` is missing, or the intervals are not ascending. Discarding the incorrect portion may result in a ChoiceFormat with empty `limits` and `formats`.
Since:
  1.1
See Also:
  - `DecimalFormat`
  - `MessageFormat`
  - Serialized Form

- ## Nested Class Summary

  ### Nested classes/interfaces declared in class NumberFormat

  `NumberFormat.Field, NumberFormat.Style`
  Modifier and Type
  Class
  Description
  `static class`
  `NumberFormat.Field`
  Defines constants that are used as attribute keys in the `AttributedCharacterIterator` returned from `NumberFormat.formatToCharacterIterator` and as field identifiers in `FieldPosition`.
  `static enum`
  `NumberFormat.Style`
  A number format style.

- ## Field Summary

  ### Fields declared in class NumberFormat

  `FRACTION_FIELD, INTEGER_FIELD`
  Modifier and Type
  Field
  Description
  `static final int`
  `FRACTION_FIELD`
  Field constant used to construct a FieldPosition object.
  `static final int`
  `INTEGER_FIELD`
  Field constant used to construct a FieldPosition object.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `ChoiceFormat(double[] limits, String[] formats)`
  Constructs with the limits and the corresponding formats.
  `ChoiceFormat(String newPattern)`
  Constructs a ChoiceFormat with limits and corresponding formats based on the pattern.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `applyPattern(String newPattern)`
  Apply the given pattern to this ChoiceFormat object.
  `Object`
  `clone()`
  Overrides Cloneable
  `boolean`
  `equals(Object obj)`
  Compares the specified object with this `ChoiceFormat` for equality.
  `StringBuffer`
  `format(double number, StringBuffer toAppendTo, FieldPosition status)`
  Returns pattern with formatted double.
  `StringBuffer`
  `format(long number, StringBuffer toAppendTo, FieldPosition status)`
  Specialization of format.
  `Object[]`
  `getFormats()`
  Returns the formats of this ChoiceFormat.
  `double[]`
  `getLimits()`
  Returns the limits of this ChoiceFormat.
  `int`
  `hashCode()`
  Returns the hash code for this `ChoiceFormat`.
  `boolean`
  `isStrict()`
  Returns `true` if this format will parse numbers strictly; `false` otherwise.
  `static final double`
  `nextDouble(double d)`
  Finds the least double greater than `d`.
  `static double`
  `nextDouble(double d, boolean positive)`
  Finds the least double greater than `d` (if `positive` is `true`), or the greatest double less than `d` (if `positive` is `false`).
  `Number`
  `parse(String text, ParsePosition status)`
  Parses the input text starting at the index given by the `ParsePosition` as a `Double`.
  `static final double`
  `previousDouble(double d)`
  Finds the greatest double less than `d`.
  `void`
  `setChoices(double[] limits, String[] formats)`
  Set the choices to be used in formatting.
  `void`
  `setStrict(boolean strict)`
  Change the leniency value for parsing.
  `String`
  `toPattern()`
  Returns a pattern `string` that represents the `limits` and `formats` of this ChoiceFormat object.
  `String`
  `toString()`
  Returns a string identifying this `ChoiceFormat`, for debugging.

  ### Methods declared in class NumberFormat

  `format, format, format, getAvailableLocales, getCompactNumberInstance, getCompactNumberInstance, getCurrency, getCurrencyInstance, getCurrencyInstance, getInstance, getInstance, getIntegerInstance, getIntegerInstance, getMaximumFractionDigits, getMaximumIntegerDigits, getMinimumFractionDigits, getMinimumIntegerDigits, getNumberInstance, getNumberInstance, getPercentInstance, getPercentInstance, getRoundingMode, isGroupingUsed, isParseIntegerOnly, parse, parseObject, setCurrency, setGroupingUsed, setMaximumFractionDigits, setMaximumIntegerDigits, setMinimumFractionDigits, setMinimumIntegerDigits, setParseIntegerOnly, setRoundingMode`
  Modifier and Type
  Method
  Description
  `final String`
  `format(double number)`
  Specialization of format.
  `final String`
  `format(long number)`
  Specialization of format.
  `StringBuffer`
  `format(Object number, StringBuffer toAppendTo, FieldPosition pos)`
  Formats a number and appends the resulting text to the given string buffer.
  `static Locale[]`
  `getAvailableLocales()`
  Returns an array of all locales for which the `get*Instance` methods of this class can return localized instances.
  `static NumberFormat`
  `getCompactNumberInstance()`
  Returns a compact number format for the default `FORMAT` locale with `"SHORT"` format style.
  `static NumberFormat`
  `getCompactNumberInstance(Locale locale, NumberFormat.Style formatStyle)`
  Returns a compact number format for the specified `locale` and `formatStyle`.
  `Currency`
  `getCurrency()`
  Gets the currency used by this number format when formatting currency values.
  `static final NumberFormat`
  `getCurrencyInstance()`
  Returns a currency format for the current default `FORMAT` locale.
  `static NumberFormat`
  `getCurrencyInstance(Locale inLocale)`
  Returns a currency format for the specified locale.
  `static final NumberFormat`
  `getInstance()`
  Returns a general-purpose number format for the current default `FORMAT` locale.
  `static NumberFormat`
  `getInstance(Locale inLocale)`
  Returns a general-purpose number format for the specified locale.
  `static final NumberFormat`
  `getIntegerInstance()`
  Returns an integer number format for the current default `FORMAT` locale.
  `static NumberFormat`
  `getIntegerInstance(Locale inLocale)`
  Returns an integer number format for the specified locale.
  `int`
  `getMaximumFractionDigits()`
  Returns the maximum number of digits allowed in the fraction portion of a number during formatting.
  `int`
  `getMaximumIntegerDigits()`
  Returns the maximum number of digits allowed in the integer portion of a number during formatting.
  `int`
  `getMinimumFractionDigits()`
  Returns the minimum number of digits allowed in the fraction portion of a number during formatting.
  `int`
  `getMinimumIntegerDigits()`
  Returns the minimum number of digits allowed in the integer portion of a number during formatting.
  `static final NumberFormat`
  `getNumberInstance()`
  Returns a general-purpose number format for the current default `FORMAT` locale.
  `static NumberFormat`
  `getNumberInstance(Locale inLocale)`
  Returns a general-purpose number format for the specified locale.
  `static final NumberFormat`
  `getPercentInstance()`
  Returns a percentage format for the current default `FORMAT` locale.
  `static NumberFormat`
  `getPercentInstance(Locale inLocale)`
  Returns a percentage format for the specified locale.
  `RoundingMode`
  `getRoundingMode()`
  Gets the `RoundingMode` used in this NumberFormat.
  `boolean`
  `isGroupingUsed()`
  Returns true if grouping is used in this format.
  `boolean`
  `isParseIntegerOnly()`
  Returns `true` if this format will parse numbers as integers only.
  `Number`
  `parse(String source)`
  Parses text from the beginning of the given string to produce a `Number`.
  `final Object`
  `parseObject(String source, ParsePosition pos)`
  Parses text from the given string to produce an object.
  `void`
  `setCurrency(Currency currency)`
  Sets the currency used by this number format when formatting currency values.
  `void`
  `setGroupingUsed(boolean newValue)`
  Set whether or not grouping will be used in this format.
  `void`
  `setMaximumFractionDigits(int newValue)`
  Sets the maximum number of digits allowed in the fraction portion of a number during formatting.
  `void`
  `setMaximumIntegerDigits(int newValue)`
  Sets the maximum number of digits allowed in the integer portion of a number during formatting.
  `void`
  `setMinimumFractionDigits(int newValue)`
  Sets the minimum number of digits allowed in the fraction portion of a number during formatting.
  `void`
  `setMinimumIntegerDigits(int newValue)`
  Sets the minimum number of digits allowed in the integer portion of a number during formatting.
  `void`
  `setParseIntegerOnly(boolean value)`
  Sets whether or not numbers should be parsed as integers only.
  `void`
  `setRoundingMode(RoundingMode roundingMode)`
  Sets the `RoundingMode` used in this NumberFormat.

  ### Methods declared in class Format

  `format, formatToCharacterIterator, parseObject`
  Modifier and Type
  Method
  Description
  `final String`
  `format(Object obj)`
  Formats an object to produce a string.
  `AttributedCharacterIterator`
  `formatToCharacterIterator(Object obj)`
  Formats an Object producing an `AttributedCharacterIterator`.
  `Object`
  `parseObject(String source)`
  Parses text from the beginning of the given string to produce an object.

  ### Methods declared in class Object

  `finalize, getClass, notify, notifyAll, wait, wait, wait`
  Modifier and Type
  Method
  Description
  `protected void`
  `finalize()`
  Deprecated, for removal: This API element is subject to removal in a future version.
  Finalization is deprecated and subject to removal in a future release.
  `final Class<?>`
  `getClass()`
  Returns the runtime class of this `Object`.
  `final void`
  `notify()`
  Wakes up a single thread that is waiting on this object's monitor.
  `final void`
  `notifyAll()`
  Wakes up all threads that are waiting on this object's monitor.
  `final void`
  `wait()`
  Causes the current thread to wait until it is awakened, typically by being notified or interrupted.
  `final void`
  `wait(long timeoutMillis)`
  Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.
  `final void`
  `wait(long timeoutMillis, int nanos)`
  Causes the current thread to wait until it is awakened, typically by being notified or interrupted, or until a certain amount of real time has elapsed.

- ## Constructor Details

  - ### ChoiceFormat

    public ChoiceFormat(String newPattern)
    Constructs a ChoiceFormat with limits and corresponding formats based on the pattern. The syntax and error related caveats for the ChoiceFormat pattern can be found in the Patterns section. Unlike `ChoiceFormat(double[], String[])`, this constructor will throw an `IllegalArgumentException` if the `limits` are not in ascending order.
    Parameters:
      `newPattern` - the new pattern string
    Throws:
      `NullPointerException` - if `newPattern` is `null`
      `IllegalArgumentException` - if `newPattern` violates the pattern syntax
    See Also:
      - `applyPattern(String)`

  - ### ChoiceFormat

    public ChoiceFormat(double[] limits, String[] formats)
    Constructs with the limits and the corresponding formats.
    Parameters:
      `limits` - limits in ascending order
      `formats` - corresponding format strings
    Throws:
      `NullPointerException` - if `limits` or `formats` is `null`
      `IllegalArgumentException` - if the length of `limits` and `formats` are not equal
    See Also:
      - `setChoices(double[], String[])`

- ## Method Details

  - ### applyPattern

    public void applyPattern(String newPattern)
    Apply the given pattern to this ChoiceFormat object. The syntax and error related caveats for the ChoiceFormat pattern can be found in the Patterns section. Unlike `setChoices(double[], String[])`, this method will throw an `IllegalArgumentException` if the `limits` are not in ascending order.
    Parameters:
      `newPattern` - a pattern string
    Throws:
      `NullPointerException` - if `newPattern` is `null`
      `IllegalArgumentException` - if `newPattern` violates the pattern syntax
    See Also:
      - `ChoiceFormat(String)`

  - ### toPattern

    public String toPattern()
    Returns a pattern `string` that represents the `limits` and `formats` of this ChoiceFormat object. The `string` returned is not guaranteed to be the same input `string` passed to either `applyPattern(String)` or `ChoiceFormat(String)`.
    Returns:
      a pattern `string` that represents the `limits` and `formats` of this ChoiceFormat object
    See Also:
      - `applyPattern(String)`

  - ### setChoices

    public void setChoices(double[] limits, String[] formats)
    Set the choices to be used in formatting.
    Parameters:
      `limits` - contains the top value that you want parsed with that format, and should be in ascending sorted order. When formatting X, the choice will be the i, where limit[i] ≤ X < limit[i+1]. If the limit array is not in ascending order, the results of formatting will be incorrect.
      `formats` - are the formats you want to use for each limit.
    Throws:
      `NullPointerException` - if `limits` or `formats` is `null`
      `IllegalArgumentException` - if the length of `limits` and `formats` are not equal

  - ### getLimits

    public double[] getLimits()
    Returns the limits of this ChoiceFormat.
    Returns:
      the limits of this ChoiceFormat

  - ### getFormats

    public Object[] getFormats()
    Returns the formats of this ChoiceFormat.
    Returns:
      the formats of this ChoiceFormat

  - ### format

    public StringBuffer format(long number, StringBuffer toAppendTo, FieldPosition status)
    Specialization of format. This method really calls `format(double, StringBuffer, FieldPosition)`. Thus, the range of longs that are supported is only equal to the range that can be stored by double. This will never be a practical limitation.
    Specified by:
      `format` in class `NumberFormat`
    Parameters:
      `number` - number to be formatted and substituted.
      `toAppendTo` - where text is appended.
      `status` - ignore no useful status is returned.
    Returns:
      the formatted StringBuffer
    Throws:
      `ArrayIndexOutOfBoundsException` - if either the `limits` or `formats` of this ChoiceFormat are empty
      `NullPointerException` - if `toAppendTo` is `null`
    See Also:
      - `Format.format(Object)`

  - ### format

    public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition status)
    Returns pattern with formatted double.
    Specified by:
      `format` in class `NumberFormat`
    Parameters:
      `number` - number to be formatted and substituted.
      `toAppendTo` - where text is appended.
      `status` - ignore no useful status is returned.
    Returns:
      the formatted StringBuffer
    Throws:
      `ArrayIndexOutOfBoundsException` - if either the `limits` or `formats` of this ChoiceFormat are empty
      `NullPointerException` - if `toAppendTo` is `null`
    See Also:
      - `Format.format(Object)`

  - ### parse

    public Number parse(String text, ParsePosition status)
    Parses the input text starting at the index given by the `ParsePosition` as a `Double`. The value returned is the `limit` corresponding to the `format` that is the longest substring of the input text. Matching is done in ascending order, when multiple `format`s match the text equivalently in strength, the first matching `limit` is returned. If there is no match, `Double.NaN` is returned.

    For example,

        var fmt = new ChoiceFormat("0#foo|1#bar|2#baz");
        fmt.parse("baz", new ParsePosition(0)); // returns 2.0
        fmt.parse("quux", new ParsePosition(0)); // returns NaN

    Specified by:
      `parse` in class `NumberFormat`
    Parameters:
      `text` - the source text.
      `status` - an input-output parameter. On input, the status.index field indicates the first character of the source text that should be parsed. On exit, if no error occurred, status.index is set to the first unparsed character in the source text. On exit, if an error did occur, status.index is unchanged and status.errorIndex is set to the first index of the character that caused the parse to fail.
    Returns:
      A Number which represents the `limit` corresponding to the `format` parsed, or `Double.NaN` if the parse fails.
    Throws:
      `NullPointerException` - if `status` is `null` or if `text` is `null` and the list of choice strings is not empty.
    See Also:
      - `NumberFormat.isStrict()`

  - ### isStrict

    public boolean isStrict()
    Description copied from class: `NumberFormat`
    Returns `true` if this format will parse numbers strictly; `false` otherwise.
    Overrides:
      `isStrict` in class `NumberFormat`
    Returns:
      `true` if this format will parse numbers strictly; `false` otherwise
    Since:
      23
    See Also:
      - Leniency Section
      - `NumberFormat.setStrict(boolean)`

  - ### setStrict

    public void setStrict(boolean strict)
    Description copied from class: `NumberFormat`
    Change the leniency value for parsing. Parsing can either be strict or lenient, by default it is lenient.
    Overrides:
      `setStrict` in class `NumberFormat`
    Parameters:
      `strict` - `true` if parsing should be done strictly; `false` otherwise
    Since:
      23
    See Also:
      - Leniency Section
      - `NumberFormat.isStrict()`

  - ### nextDouble

    public static final double nextDouble(double d)
    Finds the least double greater than `d`. If `NaN`, returns same value.

    Used to make half-open intervals.

    Implementation Note:
      This is equivalent to calling `Math.nextUp(d)`
    Parameters:
      `d` - the reference value
    Returns:
      the least double value greater than `d`
    See Also:
      - `previousDouble(double)`

  - ### nextDouble

    public static double nextDouble(double d, boolean positive)
    Finds the least double greater than `d` (if `positive` is `true`), or the greatest double less than `d` (if `positive` is `false`). If `NaN`, returns same value.
    Implementation Note:
      This is equivalent to calling `positive ? Math.nextUp(d) : Math.nextDown(d)`
    Parameters:
      `d` - the reference value
      `positive` - `true` if the least double is desired; `false` otherwise
    Returns:
      the least or greater double value

  - ### previousDouble

    public static final double previousDouble(double d)
    Finds the greatest double less than `d`. If `NaN`, returns same value.
    Implementation Note:
      This is equivalent to calling `Math.nextDown(d)`
    Parameters:
      `d` - the reference value
    Returns:
      the greatest double value less than `d`
    See Also:
      - `nextDouble(double)`

  - ### clone

    public Object clone()
    Overrides Cloneable
    Overrides:
      `clone` in class `NumberFormat`
    Returns:
      a clone of this instance.
    See Also:
      - `Cloneable`

  - ### hashCode

    public int hashCode()
    Returns the hash code for this `ChoiceFormat`.
    Overrides:
      `hashCode` in class `NumberFormat`
    Implementation Requirements:
      This method calculates the hash code value using the values returned by `getFormats()` and `getLimits()`.
    Returns:
      the hash code for this `ChoiceFormat`
    See Also:
      - `Object.hashCode()`

  - ### toString

    public String toString()
    Returns a string identifying this `ChoiceFormat`, for debugging.
    Overrides:
      `toString` in class `Object`
    Returns:
      a string identifying this `ChoiceFormat`, for debugging

  - ### equals

    public boolean equals(Object obj)
    Compares the specified object with this `ChoiceFormat` for equality. Returns true if the object is also a `ChoiceFormat` and the two formats would format any value the same.
    Overrides:
      `equals` in class `NumberFormat`
    Implementation Requirements:
      This method performs an equality check with a notion of class identity based on `getClass()`, rather than `instanceof`. Therefore, in the equals methods in subclasses, no instance of this class should compare as equal to an instance of a subclass.
    Parameters:
      `obj` - object to be compared for equality
    Returns:
      `true` if the specified object is equal to this `ChoiceFormat`
    See Also:
      - `Object.equals(Object)`