【问题标题】:How to use an enum to bind 1 or more "unformatted" string to a single formatted one?如何使用枚举将 1 个或多个“未格式化”字符串绑定到单个格式化字符串?
【发布时间】:2019-03-05 00:53:50
【问题描述】:

我有一组未格式化的字符串,我需要格式化出来。我有两者的完整列表。

这是它的一个子集:

"in room"     => "ROOM"
"in big room" => "BIG ROOM"
"in building" => "BUILDING"
"in street"   => "STREET"
"in house"    => "STANDARD"
"Room box"    => "ROOM"
"Big room box"=> "BIG ROOM"
"Street box"  => "STREET"
"Box"         => "STANDARD"
default value => "STANDARD"

有人告诉我使用enum,这样我就没有大量的ifs,但我不确定这会有什么帮助。我的枚举看起来像这样:

public enum BoxLocation {
  STANDARD("STANDARD"),
  ROOM("ROOM"),
  BIG_ROOM("BIG ROOM"),
  ...

但我不明白这将如何有助于避免大量的 if。

我应该如何将一个或多个(不超过 2 个,默认值除外)未格式化的字符串绑定到格式化的字符串,最干净的方法是什么?我在想这样的事情:

if(boxLocation.equals("in room") || boxLocation.equals("Room box"))
    boxLocation = BoxLocation.ROOM;

但是,拥有一个枚举对我有什么帮助,我不能只使用它吗?

boxLocation = "ROOM";

编辑:一些格式化的值有空格,这会改变枚举。我编辑了列表。

【问题讨论】:

  • 如果您的字典是字符串到字符串,请使用 Map<String, String> 和标准 map.get(value) 消除任何 if 语句。
  • 这不是你定义枚举常量的方式。请review.
  • 您的枚举没有帮助,因为您没有正确实现它。我猜该计划有类似STANDARD("in room") 的东西,然后是类似public BoxLocation getFrom(String s) 的方法,它查找匹配的“in room”并返回相应的枚举条目。
  • 有人链接了this similar question 并删除了但它是相关的,所以我再次添加它。

标签: java enums


【解决方案1】:

你的枚举应该是这样的:

public enum BoxLocation{
    ROOM("ROOM","in room", "Room box"),
    BUILDING("BUILDING","in building"),
    STREET("STREET","in street", "Street box"),
    STANDARD("STANDARD","in house"),
    BIG_ROOM("BIG ROOM", "in big room");

    private final List<String> values;

    BoxLocation(String ...values) {
        this.values = Arrays.asList(values);
    }
    public List<String> getValues() {
        return values;
    }
    public static String find(String name) {
        for (BoxLocation bl : BoxLocation.values()) {
            if (bl.getValues().contains(name)) {
                return bl.values.get(0);
            }
        }
        return BoxLocation.STANDARD.values.get(0);
    }
}

并使用 find 方法检索任何字符串的对应值

public static void main(String[] args) {
    String boxLoc = BoxLocation.find("xyz");
    System.out.println(boxLoc);
}

【讨论】:

  • 小改进可能是使用Set 而不是List: new HashSet&lt;&gt;(Arrays.asList(values))
  • 与正确的哈希映射相比,这是一种非常低效的查找每个字符串的方法。
  • 这几乎就是我需要的!但是(我应该提到它)我的一个值有一个空格,所以我不能返回标识符。我想我需要将格式化的值添加为第一个值并返回它。例如:BIG_ROOM("BIG ROOM", "in big room") 如果值在其中一个可能的值中,我如何返回第一个?
  • @TeleportingGoat 不确定这是否是您想要的。我已经编辑了我的答案(将返回类型更改为字符串)以从枚举参数中返回第一个字符串。
  • @RealSkeptic 对于哈希图,使用枚举真的没有意义,是吗? (我的意思是,如果我有充分的理由不使用枚举,那也很好。)
【解决方案2】:

如果枚举的名称包含在句子中的单词中,则假设选择了枚举:

public enum BoxLocation {
    ROOM, BUILDING, STREET, STANDARD, BIG_ROOM;

    private final Pattern pattern = Pattern.compile(
        name().replace('_', ' '), // take care of underscores
        Pattern.CASE_INSENSITIVE
    );

    public static BoxLocation fromValue(String sentence) {
        for (BoxLocation value : BoxLocation.values()) {
            if (value.pattern.matcher(sentence).find()) {
                return value;
            }
        }
        return STANDARD;
    }
}

然后可以这样调用:

BoxLocation boxLoc = BoxLocation.fromValue("In room");

这种方法对每个枚举使用不同的Pattern(用于java中的正则表达式的类),其正则表达式等效项如下所示:/enumname/i 其中enumname是枚举的名称,i是不区分大小写的标志。

【讨论】:

  • 你在哪里匹配未格式化的字符串和格式化的字符串?例如,您必须在某个地方定义"Box""in house"都对应于"STANDARD"
  • @TeleportingGoat BoxLocation.fromValue() 中的最后一行将处理这些情况。只有当且仅当没有先前的枚举匹配时,才会到达该行
  • 我编辑了我的问题,其中一个值中有一个空格。这如何与枚举一起使用?可以是ROOM, "BIG ROOM", BUILDING, STREET, STANDARD; 吗?
  • @TeleportingGoat 查看我的编辑,通过在创建正则表达式时将下划线替换为空格
【解决方案3】:

您需要在键的顶部向 Enum 引入某种属性字段;像这样:

public enum BoxLocation {

    ROOM("in room"), 
    BUILDING("in building"), 
   ...

    private String definition;

    BoxLocation(String definition) {
        this.definition = definition;
    }
}

然后,在你的代码中,你可以这样做

boxLocation.getDefinition().equals("in room")
Or (BoxLocation.from("in room"))

另请参阅上面汤姆的消息和http://tutorials.jenkov.com/java/enums.html#enum-valueof 以获得更多指示

【讨论】:

    【解决方案4】:

    您可以尝试对 enums 执行的操作是将 String 内容与 String 表示的 enum 值进行比较,如下所示:

    public class Solution {
    
        public static void main(String[] args) {
            String boxLocation = "in room";
    
            if (boxLocation.toUpperCase().contains(Locations.ROOM.toString())) {
                System.out.println("The box is in the room");
            } else {
                System.err.println("The box is not in the room");
            }
        }
    
        enum Locations {
            ROOM,
            BUILDING,
            STREET
        }
    }
    

    【讨论】:

    • 我不是在寻找完整的句子。我真的需要我的示例中的大写值。我正在使用从格式错误的 csv 中获取的值进行数据库插入。
    • 另外,contains 不是一个选项。我编辑了我的问题以更好地展示它("in house" => "STANDARD")。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-11
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    相关资源
    最近更新 更多