java:一长串条件,怎么办? [关闭]
Posted
技术标签:
【中文标题】java:一长串条件,怎么办? [关闭]【英文标题】:java: A long list of conditions , what to do? [closed] 【发布时间】:2012-12-23 13:57:53 【问题描述】:我需要有关在 Java 中应用条件的正确方法的建议。
我有 100 个条件,我必须根据这些条件更改将显示给用户的字符串变量的值。
一个示例条件:a<5 && (b>0 && c>8) && d>9 || x!=4
存在更多条件,但变量或多或少是相同的。
我现在正在这样做:
if(condition1)
else if(condition2)
else if(condition3)
...
一个 switch case 替代方案显然会嵌套在 if-else 中,即
if(condition1)
switch(x)
case y:
blah-blah
else if(condition2)
switch(x)
case y:
blah-blah
else if(condition3)
...
但我正在寻找一些更优雅的解决方案,例如使用具有多态支持的接口,我可以做些什么来避免代码行或应该是正确的方法。
---编辑---
我实际上在安卓设备上需要这个。但这里更像是一个 java 构造。
这是我所拥有的条件的一个小快照。如果有几个通过/失败,将添加更多。这显然需要更多带有/不带有嵌套的 if-else。在那种情况下,处理会变慢。
我现在将消息存储在一个单独的类中,其中包含我保持静态的各种字符串变量,因此如果条件为真 然后我从唯一的类中选择静态变量并显示它 一。存储结果消息是否正确。
【问题讨论】:
我不确定避免代码行。但是为了提高性能,将更频繁的案例放在首位? 恕我直言,这个问题更适合codereview.stackexchange.com 性能对您来说有多重要?因为在灵活性和可读性方面,一些更“优雅”的解决方案在 if-elses 的情况下会比丑陋的树表现得更糟糕 在我看来你的条件太多了。我认为您的设计应该改进,请添加一些有关您希望使用该代码完成的高级任务的详细信息 pKs - 然后将任何分类/规则引擎抛出窗口。下面@thkala 建议的查找表是您最好的选择,它实际上可能执行得更快,这取决于您在给定输入数据的情况下生成密钥的速度 【参考方案1】:根据条件输入的数量,您可以使用查找表,甚至是HashMap
,通过将所有输入甚至一些相对简单的复杂条件编码为单个值:
int key = 0;
key |= a?(1):0;
key |= b?(1<<1):0;
key |= (c.size() > 1)?(1<<2):0;
...
String result = table[key]; // Or result = map.get(key);
此范例具有恒定时间 (O(1)
) 复杂性的额外优势,这在某些情况下可能很重要。根据条件的复杂性,您甚至可能在代码路径中平均拥有更少的分支,而不是完整的 if-then-else
意大利面条代码,这可能会提高性能。
如果您在问题中添加更多上下文,我们可能会为您提供更多帮助。条件输入来自哪里?它们是什么样的?
还有更重要的问题:What is the actual problem that you are trying to solve?
【讨论】:
我认为这将很难维护,因为您最终会得到一长串语句,其中单个语句本身很复杂。由于这些条件用于用户消息,因此它们可能会经常更改。因此,您将在代码中创建一个维护热点。 @SpaceTrucker:我原则上同意,尽管这取决于代码的实际布局方式以及它的具体用途。很有可能,一旦 OP 让我们知道这到底是怎么回事,我们会找到一个更优雅的解决方案来处理高级任务,而不是试图从本质上回答“一个人如何编写复杂的代码” Java中的逻辑表?” @thkala 很抱歉我的回复晚了,感谢您的建议。我要显示的消息是固定的。但是正如您建议的查找表一样,我将考虑它。但是如果我只是使用 if-elses ,我实际上会在哪里滞后。 @pKs:这取决于......这确实会将字符串与您的代码的其余部分分开,但它确实存在一些模块化问题。你真的想让你的应用程序中的所有类都从那里提取它们的字符串吗?如果我是你,我会先看看 android 应用程序是如何支持国际化的 - 很可能无论如何你都必须这样做,那么为什么不从一开始就做好呢? @assylias:我不知道“很棒”,但在某些情况下它可能是一个不错的选择。至于您对int
的关注,大小无关紧要——您始终可以使用long
甚至BitSet
。至于它变得一团糟,合适的编码风格会有很大帮助——例如使用位掩码的常量。【参考方案2】:
这有很多可能性。在不了解您的域的情况下,我会创建类似(您可以想到更好的名称:P)
public interface UserFriendlyMessageBuilder
boolean meetCondition(FooObjectWithArguments args);
String transform(String rawMessage);
通过这种方式,您可以创建 UserFriendlyMessageBuilder
的 Set
并仅遍历它们以获取满足转换原始消息条件的第一个。
public class MessageProcessor
private final Set<UserFriendlyMessageBuilder> messageBuilders;
public MessageProcessor(Set<UserFriendlyMessageBuilder> messageBuilders)
this.messageBuilders = messageBuilders;
public String get(FooWithArguments args, String rawMsg)
for (UserFriendlyMessageBuilder msgBuilder : messageBuilders)
if (msgBuilder.meetCondition(args))
return msgBuilder.transform(rawMsg);
return rawMsg;
【讨论】:
这将具有 O(N) 查找时间(N 是此类分类器的数量),而不是 if-else 树的较低复杂度(log(N) 理想地用于树) @radai 我明白你的意思。 ~Log(N) 只有当他的 if/else 嵌套在另一个 if/else 中时才会发生。如果不是,它们也将是相同的 O(N)。此外,我认为对于这种简单比较的情况,所花费的时间会非常少。 @RalfHoppen if-elses 在我的情况下没有嵌套,但这可能是一个选择问题。让我们也标记它以添加关于我是否使用嵌套的天气的建议【参考方案3】:在我看来,“您对模块式产品设计的重视程度很低” 这是使用OOP语言的主要因素。
例如:如果您有 100 个条件,并且您能够制作 4 个模块,那么理论上任何要选择的模块都需要 26 个条件。
【讨论】:
【参考方案4】:这是另一种可能值得考虑的可能性。
进行每个比较,计算其真值,然后在真值表中查找得到的 boolean[]。 simplifying truth tables 上有很多现有的工作可以申请。我有一个真值表简化applet我多年前写的。您可能会发现它的源代码很有用。
这样做的代价是进行所有比较,或者至少是使用简化真值表评估表达式所需的比较。优点是管理复杂条件组合的有组织的系统。
即使您不直接在代码中使用真值表,也请考虑将编写和简化作为一种组织代码的方式。
【讨论】:
以上是关于java:一长串条件,怎么办? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
str.Format(_T("%lf"),n1),转换的字符串会出现小数点后的一长串零,怎么去掉?