Looking to associate strings to ints in a cleaner/more efficient way

寵の児 提交于 2019-12-19 04:22:39

问题


How can I improve this?

The relationship is one to one and continuous on [-1,5] so i was thinking of using enum, but I'm not sure how to compare a string value to an enum value.

If there is any better way to do this, please suggest.

Thanks!

private int evaluateWord(String sval) {
    if (sval.equals("program"))
        return 1;
    else if (sval.equals("begin"))
        return 2;
    else if (sval.equals("end"))
        return 3;
    else if (sval.equals("int"))
        return 4;
    else if (sval.equals("if"))
        return 5;
    else
        System.exit(0);

回答1:


Have you considered stuffing the mapping into a HashMap once, and then just querying the map?

For example, something like this:

 private static final Map<String,Integer> m_map = new HashMap<String,Integer>();
 static {
     m_map.put( "program", 1 );
     m_map.put( "begin", 2 );
     m_map.put( "end", 3 );
     m_map.put( "int", 4 );
     m_map.put( "if", 5 );
 }

 private int evaluateWord(String sval) {
     Integer value = m_map.get( sval );
     if ( null != value ) {
        return value;
     }
     else {
        System.exit(0);
     }
 }

By the way, it looks as if you're writing a parser. It can be reasonable to write a parser by hand. Another option to consider, unless you have a good reason to write it by hand, is a parser generator like ANTLR.




回答2:


Using an enumeration:

enum Word {
  PROGRAM(1,"program"),
  BEGIN(2,"begin"),
  END(3,"end"),
  INT(4,"int"),
  IF(5,"if");

  private final int value;
  private final String representation;

  Word(int value, String representation)
  {
    this.value = value;
    this.representation = representation;
  }

  public int value()
  { return value; }

  private static Map<String, Word> fromRep =
    new HashMap<String, EnumExample2.Word>();

  public static Word fromRepresentation(String rep) {
    if (!validRep(rep)) {
      throw new IllegalArgumentException("No rep: "+rep);
    }

    return fromRep.get(rep);
  }

  public static boolean validRep(String rep)
  { return fromRep.get(rep) != null; }

  static {
    for (Word word : Word.values()) {
      fromRep.put(word.representation, word);
    }
  }
}

Then your logic is:

private int evaluateWord(String sval) {
  if (!Word.validRep(sval)) {
    System.exit(0);
  }

  return Word.fromRepresentation(sval).value();
}



回答3:


A hashmap could work:

private static HashMap<String, Integer> lookup = new HashMap<String, Integer>();
static {
    lookup.put("program", 1);
    lookup.put("being", 2);
    lookup.put("end", 3);
    lookup.put("int", 4);
    lookup.put("if", 5);
}

private int evaluateWord(String sval) {
    if ( lookup.containsKey(sval) ) {
        return lookup.get(sval);
    }
    System.exit(0); 
}



回答4:


This is what a map is for;

Create a HashMap, add key and values to the map like

wordMap.put("program", Integer.valueOf(1));

....

then, to get the value do

Integer val = wordMap.get(sval);



回答5:


Honestly, I wouldn't worry about keeping something like this ultra efficient, but there is a change you could make. If the word you pass is the last word you check for then your program ends up performing all of the checks in your function. This shouldn't be a problem in this case, but generally you don't want to flood your program with if statements, especially if you have a lot of cases.

Use a hashtable and just insert pairs. This way, all of your evaluateWord calls will return in amortized constant time. :)

Good luck!




回答6:


Why do you need a (very subjective) "cleaner" way?

You could get more efficiency from using a hash lookup but you'd want to be certain it's called quite a bit to make the extra coding effort worthwhile. If it's something that happens infrequently (and, by that, I mean something like less than once a second), it's not worth doing (YAGNI).

One thing you might want to do for better looking code (if that's important) is to ditch the else bits, they're totally unnecessary:

private int evaluateWord(String sval) {
    if (sval.equals("program")) return 1;
    if (sval.equals("begin"))   return 2;
    if (sval.equals("end"))     return 3;
    if (sval.equals("int"))     return 4;
    if (sval.equals("if"))      return 5;
    System.exit(0);
}



回答7:


You could just use an array or hashmap to map the enum values to the string values.




回答8:


Inspired by your enum comment, I present the following. It's a bit hackish, but:

enum Word
{
    PROGRAM (1), BEGIN (2), END (3), INT (4), IF (5);

    public int value;

    public Word (int value)
    {
        this.value = value;
    }
};

int evaluateWord (String word)
{
    return Word.valueOf(word.toUpperCase( )).value;
}

I love Java enums because you can do things like this. This is especially useful if you later want to (for example) add a unique behaviour for each word, or to maintain a long list of words. Note though that it is case insensitive.

Or, alternately:

enum Word
{
    PROGRAM, BEGIN, END, INT, IF;
};

int evaluateWord (String word)
{
    return Word.valueOf(word.toUpperCase( )).ordinal( ) + 1;
}


来源:https://stackoverflow.com/questions/5698150/looking-to-associate-strings-to-ints-in-a-cleaner-more-efficient-way

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!