Pawan
Pawan

Reputation: 32321

java : better way of doing this than using if and else

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

Answers (7)

SJuan76
SJuan76

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

Nunzio Hayslip
Nunzio Hayslip

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

Tuna
Tuna

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

Rob Moore
Rob Moore

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

Paul Morie
Paul Morie

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

x4nd3r
x4nd3r

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

Code-Apprentice
Code-Apprentice

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

Related Questions