Speed up DecimalFormatSymbols.

We don't need to create temporary String objects; we can just pass a char
directly. We also don't need to initialize aspects of our native peer if
we know we're going to overwrite them straight away, and making copying
into ICU the responsibility of the icu4jni class rather than the java.text
is slightly cleaner.

Together, these changes make creating a new NumberFormat about 20% faster.
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
index 43ac3f2..7ae5f3f 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/DecimalFormatSymbols.java
@@ -27,9 +27,9 @@
 
 public class DecimalFormatSymbols implements Cloneable {
     
-    private int addr;
+    private final int addr;
     
-    private Locale loc;
+    private final Locale loc;
 
     private DecimalFormatSymbols(int addr, Locale loc) {
         this.addr = addr;
@@ -44,10 +44,44 @@
         NativeDecimalFormat.setSymbol(this.addr,
                 UNumberFormatSymbol.UNUM_CURRENCY_SYMBOL.ordinal(), localeData.currencySymbol);
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(), 
+                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(),
                 localeData.internationalCurrencySymbol);
     }
     
+    public DecimalFormatSymbols(Locale locale, java.text.DecimalFormatSymbols symbols) {
+        LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(locale);
+        this.loc = locale;
+        this.addr = NativeDecimalFormat.openDecimalFormatImpl(locale.toString(),
+                localeData.numberPattern);
+        copySymbols(symbols);
+    }
+    
+    /**
+     * Copies the java.text.DecimalFormatSymbols' settings into this object.
+     */
+    public void copySymbols(final java.text.DecimalFormatSymbols dfs) {
+        Currency currency = dfs.getCurrency();
+        if (currency == null) {
+            setCurrency(Currency.getInstance("XXX")); //$NON-NLS-1$
+        } else {
+            setCurrency(Currency.getInstance(currency.getCurrencyCode()));
+        }
+        
+        setCurrencySymbol(dfs.getCurrencySymbol());
+        setDecimalSeparator(dfs.getDecimalSeparator());
+        setDigit(dfs.getDigit());
+        setGroupingSeparator(dfs.getGroupingSeparator());
+        setInfinity(dfs.getInfinity());
+        setInternationalCurrencySymbol(dfs.getInternationalCurrencySymbol());
+        setMinusSign(dfs.getMinusSign());
+        setMonetaryDecimalSeparator(dfs.getMonetaryDecimalSeparator());
+        setNaN(dfs.getNaN());
+        setPatternSeparator(dfs.getPatternSeparator());
+        setPercent(dfs.getPercent());
+        setPerMill(dfs.getPerMill());
+        setZeroDigit(dfs.getZeroDigit());
+    }
+    
     @Override
     public boolean equals(Object object) {
         if(object == null) {
@@ -117,77 +151,64 @@
 
     public void setDecimalSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_DECIMAL_SEPARATOR_SYMBOL.ordinal(),
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_DECIMAL_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setDigit(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_DIGIT_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_DIGIT_SYMBOL.ordinal(), symbol);
     }
 
     public void setGroupingSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_GROUPING_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_GROUPING_SEPARATOR_SYMBOL.ordinal(), symbol);
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_MONETARY_GROUPING_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setInfinity(String symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_INFINITY_SYMBOL.ordinal(), 
-                symbol);
+                UNumberFormatSymbol.UNUM_INFINITY_SYMBOL.ordinal(), symbol);
     }
 
     public void setInternationalCurrencySymbol(String symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(), 
-                symbol);
+                UNumberFormatSymbol.UNUM_INTL_CURRENCY_SYMBOL.ordinal(), symbol);
     }
 
     public void setMinusSign(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_MINUS_SIGN_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_MINUS_SIGN_SYMBOL.ordinal(), symbol);
     }
 
     public void setMonetaryDecimalSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_MONETARY_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_MONETARY_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setNaN(String symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_NAN_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_NAN_SYMBOL.ordinal(), symbol);
     }
 
     public void setPatternSeparator(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_PATTERN_SEPARATOR_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_PATTERN_SEPARATOR_SYMBOL.ordinal(), symbol);
     }
 
     public void setPercent(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_PERCENT_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_PERCENT_SYMBOL.ordinal(), symbol);
     }
 
     public void setPerMill(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_PERMILL_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_PERMILL_SYMBOL.ordinal(), symbol);
     }
 
     public void setZeroDigit(char symbol) {
         NativeDecimalFormat.setSymbol(this.addr,
-                UNumberFormatSymbol.UNUM_ZERO_DIGIT_SYMBOL.ordinal(), 
-                String.valueOf(symbol));
+                UNumberFormatSymbol.UNUM_ZERO_DIGIT_SYMBOL.ordinal(), symbol);
     }
  
     public Currency getCurrency() {
diff --git a/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java b/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
index 39f7307..aa10efa 100644
--- a/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
+++ b/icu/src/main/java/com/ibm/icu4jni/text/NativeDecimalFormat.java
@@ -84,6 +84,7 @@
     static native int cloneImpl(int addr);
     
     static native void setSymbol(int addr, int symbol, String str);
+    static native void setSymbol(int addr, int symbol, char ch);
     
     static native String getSymbol(int addr, int symbol);
     
diff --git a/icu/src/main/native/DecimalFormatInterface.cpp b/icu/src/main/native/DecimalFormatInterface.cpp
index f553e0a..0b19716 100644
--- a/icu/src/main/native/DecimalFormatInterface.cpp
+++ b/icu/src/main/native/DecimalFormatInterface.cpp
@@ -68,30 +68,26 @@
     unum_close(fmt);
 }
 
-static void setSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol,
-        jstring text) {
-
-    // the errorcode returned by unum_setSymbol
+static void setSymbol(JNIEnv *env, uintptr_t addr, jint symbol,
+        const UChar* chars, int32_t charCount) {
     UErrorCode status = U_ZERO_ERROR;
-
-    // get the pointer to the number format
-    UNumberFormat *fmt = (UNumberFormat *)(int)addr;
-
-    // prepare the symbol string for the call to unum_setSymbol
-    const UChar *textChars = env->GetStringChars(text, NULL);
-    int textLen = env->GetStringLength(text);
-
-    // set the symbol
-    unum_setSymbol(fmt, (UNumberFormatSymbol) symbol, textChars, textLen,
-            &status);
-
-    // release previously allocated space
-    env->ReleaseStringChars(text, textChars);
-
-    // check if an error occurred
+    UNumberFormat* fmt = reinterpret_cast<UNumberFormat*>(addr);
+    unum_setSymbol(fmt, static_cast<UNumberFormatSymbol>(symbol),
+            chars, charCount, &status);
     icu4jni_error(env, status);
 }
 
+static void setSymbol_String(JNIEnv *env, jclass, jint addr, jint symbol, jstring s) {
+    const UChar* chars = env->GetStringChars(s, NULL);
+    const int32_t charCount = env->GetStringLength(s);
+    setSymbol(env, addr, symbol, chars, charCount);
+    env->ReleaseStringChars(s, chars);
+}
+
+static void setSymbol_char(JNIEnv *env, jclass, jint addr, jint symbol, jchar ch) {
+    setSymbol(env, addr, symbol, &ch, 1);
+}
+
 static jstring getSymbol(JNIEnv *env, jclass clazz, jint addr, jint symbol) {
 
     uint32_t resultlength, reslenneeded;
@@ -773,7 +769,8 @@
     {"openDecimalFormatImpl", "(Ljava/lang/String;Ljava/lang/String;)I",
             (void*) openDecimalFormatImpl},
     {"closeDecimalFormatImpl", "(I)V", (void*) closeDecimalFormatImpl},
-    {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol},
+    {"setSymbol", "(IIC)V", (void*) setSymbol_char},
+    {"setSymbol", "(IILjava/lang/String;)V", (void*) setSymbol_String},
     {"getSymbol", "(II)Ljava/lang/String;", (void*) getSymbol},
     {"setAttribute", "(III)V", (void*) setAttribute},
     {"getAttribute", "(II)I", (void*) getAttribute},
diff --git a/text/src/main/java/java/text/DecimalFormat.java b/text/src/main/java/java/text/DecimalFormat.java
index 480d79d..7a85e71 100644
--- a/text/src/main/java/java/text/DecimalFormat.java
+++ b/text/src/main/java/java/text/DecimalFormat.java
@@ -564,9 +564,9 @@
      */
     public DecimalFormat() {
         Locale locale = Locale.getDefault();
+        // BEGIN android-changed
         icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
         symbols = new DecimalFormatSymbols(locale);
-        // BEGIN android-changed
         LocaleData localeData = com.ibm.icu4jni.util.Resources.getLocaleData(Locale.getDefault());
         dform = new com.ibm.icu4jni.text.DecimalFormat(localeData.numberPattern, icuSymbols);
         // END android-changed
@@ -588,7 +588,9 @@
      */
     public DecimalFormat(String pattern) {
         Locale locale = Locale.getDefault();
+        // BEGIN android-changed
         icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
+        // END android-changed
         symbols = new DecimalFormatSymbols(locale);
         dform = new com.ibm.icu4jni.text.DecimalFormat(pattern, icuSymbols);
 
@@ -612,9 +614,9 @@
     public DecimalFormat(String pattern, DecimalFormatSymbols value) {
         symbols = (DecimalFormatSymbols) value.clone();
         Locale locale = symbols.getLocale();
-        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
-        copySymbols(icuSymbols, symbols);
-
+        // BEGIN android-changed
+        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale, symbols);
+        // END android-changed
         dform = new com.ibm.icu4jni.text.DecimalFormat(pattern, icuSymbols);
 
         super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
@@ -1045,7 +1047,7 @@
         if (value != null) {
             symbols = (DecimalFormatSymbols) value.clone();
             icuSymbols = dform.getDecimalFormatSymbols();
-            copySymbols(icuSymbols, symbols);
+            icuSymbols.copySymbols(symbols); // android-changed
             dform.setDecimalFormatSymbols(icuSymbols);
         }
     }
@@ -1386,16 +1388,11 @@
         this.serialVersionOnStream = fields.get("serialVersionOnStream", 0);
 
         Locale locale = (Locale) Format.getInternalField("locale", symbols);
-        // BEGIN android-removed
-        // dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$
-        //         new com.ibm.icu4jni.text.DecimalFormatSymbols(locale));
-        // END android-removed
-        // BEGIN android-added
-        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
-        copySymbols(icuSymbols, symbols);
+        // BEGIN android-changed
+        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale, symbols);
         dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$
                 icuSymbols);
-        // END android-added
+        // END android-changed
         setInternalField("useExponentialNotation", dform, Boolean
                 .valueOf(useExponentialNotation));
         setInternalField("minExponentDigits", dform,
@@ -1434,41 +1431,6 @@
     }
 
     /*
-     * Copies decimal format symbols from text object to ICU one.
-     * 
-     * @param icu the object which receives the new values. @param dfs the
-     * object which contains the new values.
-     */
-    private void copySymbols(final com.ibm.icu4jni.text.DecimalFormatSymbols icu,
-            final DecimalFormatSymbols dfs) {
-        Currency currency = dfs.getCurrency();
-        // BEGIN android-changed
-        if (currency == null) {
-            icu.setCurrency(Currency.getInstance("XXX")); //$NON-NLS-1$
-        } else {
-            icu.setCurrency(Currency.getInstance(dfs.getCurrency()
-                    .getCurrencyCode()));
-        }
-        // END android-changed
-       
-        icu.setCurrencySymbol(dfs.getCurrencySymbol());
-        icu.setDecimalSeparator(dfs.getDecimalSeparator());
-        icu.setDigit(dfs.getDigit());
-        icu.setGroupingSeparator(dfs.getGroupingSeparator());
-        icu.setInfinity(dfs.getInfinity());
-        icu
-                .setInternationalCurrencySymbol(dfs
-                        .getInternationalCurrencySymbol());
-        icu.setMinusSign(dfs.getMinusSign());
-        icu.setMonetaryDecimalSeparator(dfs.getMonetaryDecimalSeparator());
-        icu.setNaN(dfs.getNaN());
-        icu.setPatternSeparator(dfs.getPatternSeparator());
-        icu.setPercent(dfs.getPercent());
-        icu.setPerMill(dfs.getPerMill());
-        icu.setZeroDigit(dfs.getZeroDigit());
-    }
-
-    /*
      * Sets private field value by reflection.
      * 
      * @param fieldName the field name to be set @param target the object which