diff --git a/.gitattributes b/.gitattributes index 7f14ac68542..7d7b04f6c10 100644 --- a/.gitattributes +++ b/.gitattributes @@ -272,6 +272,7 @@ icu4j/main/classes/core/.settings/edu.umd.cs.findbugs.core.prefs -text icu4j/main/classes/core/.settings/org.eclipse.core.resources.prefs -text icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text icu4j/main/classes/core/manifest.stub -text +icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java -text icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java -text icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java -text icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java new file mode 100644 index 00000000000..cf65de57883 --- /dev/null +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java @@ -0,0 +1,41 @@ +/* +********************************************************************** +* Copyright (c) 2004-2013, International Business Machines +* Corporation and others. All Rights Reserved. +********************************************************************** +*/ +package com.ibm.icu.impl; + +import java.text.FieldPosition; + +/** + * DontCareFieldPosition is a subclass of FieldPosition that indicates that the + * caller is not interested in the start and end position of any field. + *
+ * DontCareFieldPosition is a singleton, and its instance is immutable. + *
+ * A format
method use fpos == DontCareFieldPosition.INSTANCE
+ * to tell whether or not it needs to calculate a field position.
+ *
+ */
+public final class DontCareFieldPosition extends FieldPosition {
+
+ public static final DontCareFieldPosition INSTANCE = new DontCareFieldPosition();
+
+ private DontCareFieldPosition() {
+ // Pick some random number to be sure that we don't accidentally match with
+ // a field.
+ super(-913028704);
+ }
+
+ @Override
+ public void setBeginIndex(int i) {
+ // Do nothing
+ }
+
+ @Override
+ public void setEndIndex(int i) {
+ // Do nothing
+ }
+
+}
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java
index d1ea18545d1..7511f0fb473 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java
@@ -28,6 +28,7 @@ import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.Set;
+import com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.util.Currency;
@@ -239,6 +240,10 @@ public class MeasureFormat extends UFormat {
* then its indices are set to the beginning and end of the first such field
* encountered. MeasureFormat itself does not supply any fields.
*
+ * Calling a
+ * formatMeasures
method is preferred over calling
+ * this method as they give better performance.
+ *
* @param obj must be a Collection extends Measure>, Measure[], or Measure object.
* @param toAppendTo Formatted string appended here.
* @pram pos Identifies a field in the formatted text.
@@ -296,7 +301,7 @@ public class MeasureFormat extends UFormat {
*/
public String formatMeasures(Measure... measures) {
StringBuilder result = this.formatMeasures(
- new StringBuilder(), new FieldPosition(0), measures);
+ new StringBuilder(), DontCareFieldPosition.INSTANCE, measures);
return result.toString();
}
@@ -335,48 +340,29 @@ public class MeasureFormat extends UFormat {
}
}
- // Zero out our field position so that we can tell when we find our field.
- FieldPosition fpos = new FieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
- FieldPosition dummyPos = new FieldPosition(0);
-
- int fieldPositionFoundIndex = -1;
- StringBuilder[] results = new StringBuilder[measures.length];
- for (int i = 0; i < measures.length; ++i) {
- if (fieldPositionFoundIndex == -1) {
- results[i] = formatMeasure(measures[i], new StringBuilder(), fpos);
- if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
- fieldPositionFoundIndex = i;
- }
- } else {
- results[i] = formatMeasure(measures[i], new StringBuilder(), dummyPos);
- }
- }
ListFormatter listFormatter = ListFormatter.getInstance(getLocale(),
length == FormatWidth.WIDE ? ListFormatter.Style.DURATION : ListFormatter.Style.DURATION_SHORT);
-
- // Fix up FieldPosition indexes if our field is found.
- if (fieldPositionFoundIndex != -1) {
- String listPattern = listFormatter.getPatternForNumItems(measures.length);
- int positionInPattern = listPattern.indexOf("{" + fieldPositionFoundIndex + "}");
- if (positionInPattern == -1) {
- throw new IllegalStateException("Can't find position with ListFormatter.");
- }
- // Now we have to adjust our position in pattern
- // based on the previous values.
- for (int i = 0; i < fieldPositionFoundIndex; i++) {
- positionInPattern += (results[i].length() - ("{" + i + "}").length());
- }
- fieldPosition.setBeginIndex(fpos.getBeginIndex() + positionInPattern);
- fieldPosition.setEndIndex(fpos.getEndIndex() + positionInPattern);
- }
+ String[] results = null;
+ if (fieldPosition == DontCareFieldPosition.INSTANCE) {
+ // Fast track: No field position.
+ results = new String[measures.length];
+ for (int i = 0; i < measures.length; i++) {
+ results[i] = formatMeasure(measures[i]);
+ }
+ } else {
+
+ // Slow track: Have to calculate field position.
+ results = formatMeasuresSlowTrack(listFormatter, fieldPosition, measures);
+ }
+
// This is safe because appendable is of type T.
try {
return (T) appendable.append(listFormatter.format((Object[]) results));
} catch (IOException e) {
throw new RuntimeException(e);
}
- }
+ }
/**
* Two MeasureFormats, a and b, are equal if and only if they have the same width,
@@ -612,6 +598,12 @@ public class MeasureFormat extends UFormat {
return unitToStyleToCountToFormat;
}
+ private String formatMeasure(Measure measure) {
+ return formatMeasure(
+ measure, new StringBuilder(),
+ DontCareFieldPosition.INSTANCE).toString();
+ }
+
private