1
\$\begingroup\$

Java program uses the following construction: (provided mainly for context)

public class Utils {
  public static final byte PROVIDER_FOO = 0;
  public static final byte PROVIDER_MOO = 1;
  public static final byte PROVIDER_BAR = 2;
  public static final byte PROVIDER_FUR = 3;
  public static final byte PROVIDER_BOO = 4;
  public static final byte PROVIDER_ANOTHER_FOO = 5;
  public static final byte PROVIDER_YET_ANOTHER = 6;

  public static String [] PROVIDERS = {"FOO", "MOO", "BAR", "FUR", "BOO",
    "PROVIDER_ANOTHER_FOO", "PROVIDER_YET_ANOTHER"};

  ...

}

So, each element of array has a number. And each array index in range 0..6 has text representation. Text representation is using in outer world: reading configs, printing results. Number representation is using in internal tasks. So, there a problem to transform text representation to number and vice versa. Number is transferring to string as following:

// someObject.getProviderNumeric() returns numeric value for someObj's provider
String strProvider = Utils.PROVIDERS[someObj.getProviderNumeric()] 

String is transferring to number like this:

int getNumericByText(String strProvider) {
  for (int i = 0; i < Utils.PROVIDER_YET_ANOTHER; ++i) {
    if (strProvider.equals(Utils.PROVIDERS[i])) {
      return i;
  }
  return -1;
}

It looks pretty bulky. What is the best way to rewrite?

\$\endgroup\$
2
  • \$\begingroup\$ I am on the fence with this question. It looks very much like example code, which I think/hope you have heard before that we don't like here. Unlike Stack Overflow, we prefer to look at real code instead of example code. That said, I feel that most of your example code is only provided as context for your problem, which is why I currently have not voted to close. \$\endgroup\$ Jul 8, 2015 at 16:10
  • \$\begingroup\$ @SimonAndréForsberg - Thank you for your answer (+1). Actually the code in my questions is pretty coincide to the code in production. It was just renaming and some reduction. \$\endgroup\$
    – Loom
    Jul 9, 2015 at 14:34

2 Answers 2

4
\$\begingroup\$

In my opinion, what you need is an enum.

Use an enum and I believe what you are looking for will be provided for you.

public enum Utils {
    PROVIDER_FOO, PROVIDER_MOO, PROVIDER_BAR, PROVIDER_FUR,
    PROVIDER_BOO, PROVIDER_ANOTHER_FOO, PROVIDER_YET_ANOTHER;
}

String to int:

Utils.valueOf(str).ordinal();

int to String:

Utils.values()[intValue].name();

Or if you want to be a bit more advanced, I suggest reading this answer of mine

\$\endgroup\$
2
  • \$\begingroup\$ Thank you! Utils.values[intValue].name(); doesn't work for me. Did you mean Utils.values()[intValue].name();? \$\endgroup\$
    – Loom
    Jul 9, 2015 at 14:49
  • \$\begingroup\$ @Loom yes, exactly! \$\endgroup\$ Jul 9, 2015 at 14:56
4
\$\begingroup\$

The obvious solution is to use an enum with custom fields for the numeric value and the custom string representation, and a static map to cache the mapping of string values to the enumerated values. Something like this:

enum Provider {
    FOO(0, "Foo"),
    MOO(1, " Moo"),
    BAR(2, "Bar");

    private final byte value;
    private final String label;

    private static final Map<String, Provider> map;
    static {
        map = new HashMap<>();
        for (Provider provider : Provider.values()) {
            map.put(provider.label, provider);
        }
    }

    private Provider(byte value, String label) {
        this.value = value;
        this.label = label;
    }

    public static Provider fromString(String label) {
        return map.get(label);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.