【问题标题】:java: create a lookup table using hashmap or some other java collection?java:使用 hashmap 或其他 java 集合创建查找表?
【发布时间】:2012-12-24 12:56:40
【问题描述】:

Extending this question,我已经接受了一个答案,即 使用查找表或哈希映射 用于这种情况,因为它会是一个更好的处理多个条件的构造。。 p>

当前构造。

用于存储消息的类。

    public class ProgressMessages 
    {
     public static String msg1="Welcome here .....";
     .
     .
     .
     //around 100 more similar static variables.
    }

条件并显示来自上述类的正确消息。

    int x=calculatedVal1(m,n); 
    int y=calculatedVal2(o,q);

    SimpleDateFormat formater=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date d=new Date();
    String s=formater.format(d);

    try {
          long d1 = formater.parse("2013-01-10 13:53:01").getTime();
          long d2=formater.parse(s).getTime();
          totaldays=Math.abs((d1-d2)/(1000*60*60*24));
         } catch (ParseException e) {
            e.printStackTrace();
         }

    if(totaldays<7&&x<20)
     {
      System.out.println("my message...1"+ProgressMessages.msg1); 
     }

    else if(totaldays<7&&x>10&&y<20)
    {
      System.out.println("my message...2"+ProgressMessages.msg2);
    }   
    ....
    //obvioulsy 100 more else-if's to display 100 messages.

我实际上想知道查找表对此有何帮助 案例?

应该如何在java Hashmap/Hashtable等中实现,有什么好处呢?

----编辑---

我选择@assylias anwer,因为它更干净。但是如果我使用 Enums,那么我就有了解决办法。

描述全局...

即消息列表就像...

1) "Welcome," + nameOfUser+"你的成功率是"+ succssRate +"%"+ 之前是+earlier +"%"。

2) “哦,是的..”+ succssRate +“%”+ 从 +earlier +“%” 改进。

3.) “现在你应该专注于”+exerCiseName。

我如何使用枚举来做到这一点,因为它具有固定的字符串数据。我可以制作不同的构造函数吗? assylas 的编辑代码示例如何回答?

【问题讨论】:

  • 这基本上都在answer you accepted 中。优点是它比 if/else 树更快,因为您可以根据您的条件计算索引并在恒定时间内进行查找。实现它的最简单方法是简单的String[]
  • @jlordo 我怎么能记住 String[] 中变量的索引,但是使用具有正确含义的变量名会更符合语义,这就是我在这里不使用 String[] 的原因。那么我如何在代码中实现它,你能修改它或进一步解释。
  • 查看other answer。您使用您的条件来计算索引,然后使用存储在该索引处的消息。这是一种干净的方法,可以在恒定时间内工作,并且避免了大的 if then else 混乱。
  • @jlordo 我认为实现起来并不容易。特别是,可能有超过 32 种不同的条件,因此使用 32 位密钥 + 位移将无法考虑所有可能的组合。
  • @pKs:现在我确定我们正在谈论 Y :) 这是另一个很好的描述:What is the XY problem?。您可以将变量放入字符串中并使用String.format()。但是为什么你有 100+ 条欢迎信息的条件???当您向我们描述您正在尝试做的事情(大图)时,我们可能会为您提供更好的解决方案。

标签: java collections lookup


【解决方案1】:

如果你有这么多条件,你不能避免将这些条件放在代码中的某个位置。 使用查找表的优点是 1)易于实施。 2)灵活。如果你以后想改变一些消息的值,你可以去looktable类改变。

【讨论】:

  • 在这种情况下如何使用地图?
  • 我可以接受条件,因为它们将在代码本身中实现,但是你认为创建一个类并将变量存储为静态是正确的,我怎么能这样做呢? java端本身的查找表。
  • 创建一个类并将变量存储为静态是正确的方法。这就是您可以实现查找表的方式。
  • @assylias 我不确定这一点,但关于条件之间的索引,我需要一些解释的实施方式,正如我在我的问题中提到的那样,我接受的答案是在说些什么。
【解决方案2】:

假设消息列表在编译时已知,您可以使用枚举。优点是现在每条消息都负责保持它的条件,调用代码会简单得多。

public enum Message {

    MESSAGE1("Welcome") {
        @Override
        boolean isApplicable(long totalDays, int x, int y) {
            return totalDays < 7 && x < 20;
        }
    },
    MESSAGE2("Bye bye") {
        @Override
        boolean isApplicable(long totalDays, int x, int y) {
            return totalDays < 7 && x > 10 && y < 20;
        }
    };

    private String msg;

    Message(String msg) {
        this.msg = msg;
    }

    abstract boolean isApplicable(long totalDays, int x, int y);

    public static String lookupMessage(long totalDays, int x, int y) {
        for (Message m : Message.values()) {
            if (m.isApplicable(totalDays, x, y)) {
                return m.msg;
            }
        }
        throw new IllegalArgumentException();
    }
}

现在在你的调用代码中,不再有 if / else if,只有一行代码:

System.out.println(Message.lookupMessage(1, 2, 3));

注意 1:这不如使用 Map 高效,因为查找是 O(n) 操作,但因为 n 是 100 左右,所以它不应该是显着的性能损失。而且它比其他答案中提出的解决方案更具可读性和可维护性。

注意 2:您甚至可以将条件/消息放在一个平面文件中,在运行时读取该文件并使用脚本引擎在运行时评估每个条件。它会稍微慢一些(但我们在这里谈论的是亚毫秒),但会从您的代码中删除所有混乱并将其放入配置文件中。

【讨论】:

  • 你的方法比我现在在我的问题中所做的更好吗?
  • 猜猜这很干净很酷,如果我采用这种方法,您能否建议我如何在消息中添加一些数据,即 Welcome + nameOfUser。
  • @pKs 更好地取决于您的标准。性能方面是相似的。它看起来也更干净。一旦你有了“欢迎”部分,你就可以连接任何你想要的东西,比如用户名......
【解决方案3】:

我会用一个

Map<Criteria, Message> lookupTable;

其中Criteria 是您编写的类(并覆盖equals()hashCode()),表示选择消息的标准。

Message也是你写的一个类,它封装了实际的消息String,同时也为你提供了一些设置变量的功能。

使用此解决方案,您必须在程序开始时初始化地图一次,并且始终可以像这样使用它:

Criteria criteria = ... // gather your criteria somehow
Message msg = lookupTable.getMessage(criteria);
// use your variable setting methods here
String message = msg.toString();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    • 2021-12-23
    相关资源
    最近更新 更多