From 276ed569105d5e0fda01055c4a449fd5e2b080f7 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Tue, 13 Nov 2018 23:00:53 +0000 Subject: [PATCH] cache and reuse DecimalFormat instances git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1222 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../jackcess/expr/LocaleContext.java | 7 ++++++ .../jackcess/impl/BaseEvalContext.java | 5 ++++ .../jackcess/impl/DBEvalContext.java | 14 +++++++++++ .../jackcess/impl/expr/DefaultFunctions.java | 25 ++++++++++--------- .../impl/expr/ExpressionatorTest.java | 6 +++++ 5 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/healthmarketscience/jackcess/expr/LocaleContext.java b/src/main/java/com/healthmarketscience/jackcess/expr/LocaleContext.java index d086836..a90a80b 100644 --- a/src/main/java/com/healthmarketscience/jackcess/expr/LocaleContext.java +++ b/src/main/java/com/healthmarketscience/jackcess/expr/LocaleContext.java @@ -16,6 +16,7 @@ limitations under the License. package com.healthmarketscience.jackcess.expr; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -50,4 +51,10 @@ public interface LocaleContext * {@link EvalConfig}) */ public NumericConfig getNumericConfig(); + + /** + * @return an appropriately configured (i.e. DecimalFormatSymbols) + * DecimalFormat for the given format. + */ + public DecimalFormat createDecimalFormat(String formatStr); } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java b/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java index bd7298e..0e52fa4 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java @@ -18,6 +18,7 @@ package com.healthmarketscience.jackcess.impl; import java.io.IOException; import java.math.BigDecimal; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collection; @@ -93,6 +94,10 @@ public abstract class BaseEvalContext implements EvalContext return _dbCtx.getNumericConfig(); } + public DecimalFormat createDecimalFormat(String formatStr) { + return _dbCtx.createDecimalFormat(formatStr); + } + public float getRandom(Integer seed) { return _dbCtx.getRandom(seed); } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DBEvalContext.java b/src/main/java/com/healthmarketscience/jackcess/impl/DBEvalContext.java index 7fcfcb8..b1e9995 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/DBEvalContext.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/DBEvalContext.java @@ -16,6 +16,7 @@ limitations under the License. package com.healthmarketscience.jackcess.impl; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Map; @@ -41,6 +42,7 @@ public class DBEvalContext implements Expressionator.ParseContext, EvalConfig private final DatabaseImpl _db; private FunctionLookup _funcs = DefaultFunctions.LOOKUP; private Map _sdfs; + private Map _dfs; private TemporalConfig _temporal = TemporalConfig.US_TEMPORAL_CONFIG; private NumericConfig _numeric = NumericConfig.US_NUMERIC_CONFIG; private final RandomContext _rndCtx = new RandomContext(); @@ -103,6 +105,18 @@ public class DBEvalContext implements Expressionator.ParseContext, EvalConfig return sdf; } + public DecimalFormat createDecimalFormat(String formatStr) { + if(_dfs == null) { + _dfs = new SimpleCache(MAX_CACHE_SIZE); + } + DecimalFormat df = _dfs.get(formatStr); + if(df == null) { + df = new DecimalFormat(formatStr, _numeric.getDecimalFormatSymbols()); + _dfs.put(formatStr, df); + } + return df; + } + public float getRandom(Integer seed) { return _rndCtx.getRandom(seed); } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java index c5d0e8f..7a582d6 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java @@ -549,12 +549,15 @@ public class DefaultFunctions fmt.append("\u00A4"); } + if(groupDigits) { + fmt.append("#,"); + appendNum(fmt, '#', numGroupDigits - 1); + } + fmt.append(incLeadDigit ? "0" : "#"); if(numDecDigits > 0) { fmt.append("."); - for(int i = 0; i < numDecDigits; ++i) { - fmt.append("0"); - } + appendNum(fmt, '0', numDecDigits); } if(isPercent) { @@ -569,15 +572,7 @@ public class DefaultFunctions } // Note, DecimalFormat rounding mode uses HALF_EVEN by default - DecimalFormat df = new DecimalFormat( - fmt.toString(), cfg.getDecimalFormatSymbols()); - if(groupDigits) { - df.setGroupingUsed(true); - df.setGroupingSize(numGroupDigits); - } else { - df.setGroupingUsed(false); - df.setGroupingSize(numGroupDigits); - } + DecimalFormat df = ctx.createDecimalFormat(fmt.toString()); return ValueSupport.toValue(df.format(param1.getAsBigDecimal(ctx))); } @@ -602,4 +597,10 @@ public class DefaultFunctions throw new IllegalStateException("Duplicate function " + fname); } } + + private static void appendNum(StringBuilder sb, char c, int num) { + for(int i = 0; i < num; ++i) { + sb.append(c); + } + } } diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java index 4c50f12..17ad3d7 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java @@ -19,6 +19,7 @@ package com.healthmarketscience.jackcess.impl.expr; import java.io.BufferedReader; import java.io.FileReader; import java.math.BigDecimal; +import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @@ -604,6 +605,11 @@ public class ExpressionatorTest extends TestCase return NumericConfig.US_NUMERIC_CONFIG; } + public DecimalFormat createDecimalFormat(String formatStr) { + return new DecimalFormat( + formatStr, NumericConfig.US_NUMERIC_CONFIG.getDecimalFormatSymbols()); + } + public FunctionLookup getFunctionLookup() { return DefaultFunctions.LOOKUP; } -- 2.39.5