Reputation: 32321
I have a requirement were depending on a particular key value of a map , i need to format the output .
For example if its value greater than 1 then needed to display only 2 decimal points after the value (12.23) or else if its value is less than 1 , i need to show 4 decimal points after it .
I have written the code its working fine , but i am looking for a better way of doing this (basically i didn't liked if else conditions in my code )
This is my program where depending on the last attribute key value i am formatting the output
package com;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class CustValues {
public static void main(String args[]) {
Map valuesMap = new HashMap();
valuesMap.put("mktCap", "12.4d");
valuesMap.put("last", "0.4344");
valuesMap.put("avgvalue", "34.55");
valuesMap.put("bidprice", "44.44");
Iterator<String> iterator = valuesMap.keySet().iterator();
while (iterator.hasNext()) {
String name = iterator.next().toString();
String value = (String) valuesMap.get(name);
if (name.equals("last")) {
String result = "";
double d = Double.parseDouble(value);
if (d > 1) {
result = formatNumber(value, 2);
} else {
result = formatNumber(value, 4);
}
System.out.println(result);
}
}
}
public static String formatNumber(String s, int decPts) {
double d = Double.parseDouble(s);
if (2 == decPts)
return new DecimalFormat("#,###,###,##0.00").format(d);
else if (0 == decPts)
return new DecimalFormat("#,###,###,##0").format(d);
else if (3 == decPts)
return new DecimalFormat("#,###,###,##0.000").format(d);
else if (4 == decPts)
return new DecimalFormat("0.0000").format(d);
return String.valueOf(d);
}
}
Upvotes: 0
Views: 279
Reputation: 24780
You can use the switch
sentence
switch (decPts) {
case 0:
return new DecimalFormat("#,###,###,##0").format(d);
case 2:
...
}
It helps tidy the code for this case. Anyway you would not be able to program in any language without using ìf
or similar constructs.
Upvotes: 1
Reputation: 21
One really inefficient, but more flexible option would be to generate the format string based on decPts:
public static String formatNumber(String s, int decPts) {
double d = Double.parseDouble(s);
final String baseFormat = "#,###,###,##0";
// TODO: Use a StringBuilder
String format = decPts==0 ? baseFormat : baseFormat + ".";
for (int i=0; i < decPts; i++) {
format += "0";
}
return new DecimalFormat(format).format(d);
}
Again, this is a bad idea unless you need to show an arbitrary number of decimal points or can only determine the way to display the number at run-time, which probably isn't the case.
Upvotes: 0
Reputation: 2995
I have method as below:
public static String formatNumber(String s, int decPts) {
double d = Double.parseDouble(s);
if (decPts >= 0 && decPts <= 4) {
DecimalFormat df = new DecimalFormat("###,##0");
df.setMaximumFractionDigits(decPts);
df.setMinimumFractionDigits(decPts);
return df.format(d);
}
return String.valueOf(d);
}
Upvotes: 1
Reputation: 3383
Building on Code-Guru's answer. You can use a map but to retain the same thread safety and default behavior the code becomes:
public class CustValues {
private static final Map<Integer, String> FORMATS;
static {
Map<Integer, String> formats = new HashMap<Integer, String>();
formats.put( 0, "#,###,###,##0" );
formats.put( 2, "#,###,###,##0.00" );
formats.put( 3, "#,###,###,##0.000" );
formats.put( 4, "0.0000" );
FORMATS = Collections.unmodifiableMap( formats );
}
public static void main(String args[]) {
// Same as before....
}
public static String formatNumber(String s, int decPts) {
double d = Double.parseDouble(s);
String format = FORMATS.get(decPts);
if( format != null ) {
return new DecimalFormat(format).format(d);
}
return String.valueOf(d);
}
}
You need to create a new DecimalFormat for each request instead of reusing it since it is not thread safe. This also handles the cases where decPts is not 0, 2, 3, or 4.
Upvotes: 1
Reputation: 15778
Enums have the advantage of avoiding boxing and unboxing an integer that a map.get call would perform, while only creating the formatters you need one time. Note, you can also could get rid of the second double parse:
enum DisplayFormat {
CURRENCY(new DecimalFormat("#,###,###,#00.00")),
SMALL_CURRENCY(new DecimalFormat("0.000"));
private DecimalFormat f;
public DisplayFormat(DecimalFormat f) {
this.f = f;
}
public String format(double d) {
return this.f.format(d);
}
// Usage:
if (name.equals("last")) {
String result = "";
double d = Double.parseDouble(value);
if (d > 1) {
result = DisplayFormat.SMALL_CURRENCY.format(d)
} else {
result = DisplayFormat.CURRENCY.format(d)
}
System.out.println(result);
}
Upvotes: 0
Reputation: 900
The logic you're implementing in the formatNumber
method is the perfect candidate for a switch statement. Try
switch (decPts) {
case 0:
return new DecimalFormat("#,###,###,##0").format(d);
break;
case 2:
return new DecimalFormat("#,###,###,##0.00").format(d);
break;
...
}
For more info see this tutorial.
edit: Although SJuan76 beat me to it, and I like Code-Guru's idea better!
Upvotes: 1
Reputation: 83517
You could create a Map<Integer, DecimalFormat> formats
(or a List<DecimalFormat>
, if you prefer). Then formatNumber()
simply calls formats.get(decPts)
to get the correct format.
Upvotes: 5