java Freemarker:如何使用枚举作为键遍历 Map

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5422412/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:02:36  来源:igfitidea点击:

Freemarker: How to iterate through the Map using enums as keys

javaenumsmapkeyfreemarker

提问by Alex Vayda

The following code does not work because Freemarker seems to cast the value of the expression inside [] to String and then to use it as a key, which is not what is actually expected.

以下代码不起作用,因为 Freemarker 似乎将 [] 中表达式的值转换为 String 然后将其用作键,这不是实际预期的。

Preparing a template model:

准备模板模型:

Map<MyEnum, Object> myMap;
myMap.put(MyEnum.FOO, "Foo");
myMap.put(MyEnum.BAR, "Bar");
templateModel.put("myMap", myMap);

my.ftl:

我的.ftl:

<#list myMap?keys as key>
    <#assign value = myMap[key]>
    <li>${key} = ${value}</li>
</#list>

In the Freemarker documentationit is described how to access the Enum itself, but I didn't find anything about how to get a value from a hash using Enum as a key.

Freemarker 文档中,描述了如何访问 Enum 本身,但我没有找到任何关于如何使用 Enum 作为键从散列中获取值的信息。

Thank you.

谢谢你。

采纳答案by Andy

To paraphrase Freemarker Documentation FAQon this,

解释一下Freemarker 文档常见问题解答

You can't use non-string keys in the myMap[key] expression. You can use methods!

您不能在 myMap[key] 表达式中使用非字符串键。你可以使用方法!

So, you could create a bean that provides a way for you to get to your Java EnumMap, (i.e). Then just instantiate this bean with your mapp, and put the bean in your Model.

因此,您可以创建一个 bean,为您提供一种获取 Java EnumMap 的方法,(即)。然后用你的 mapp 实例化这个 bean,并将 bean 放入你的模型中。

class EnumMap
{
    HashMap<MyEnum, String> map = new HashMap<MyEnum, String>();

    public String getValue(MyEnum e)
    {
        return map.get(e);
    }    
    ..constructor, generics, getters, setters left out.
}

I'm a little bit confused about what general goal your trying to accomplish. If you just need to list out the values of the enum (or perhaps a display value for each one). There is a much easier way to do it.

我对您试图实现的总体目标感到有些困惑。如果您只需要列出枚举的值(或者每个枚举的显示值)。有一种更简单的方法来做到这一点。

One way I've seen this problem solved is by putting a display value on the Enum instances.

我看到这个问题解决的一种方法是在 Enum 实例上放置一个显示值。

i.e

IE

enum MyEnum 
{   FOO("Foo"), 
    BAR_EXAMPLE("Bar Example"); 
    private String displayValue;

    MyEnum(String displayValue)
    {
        this.displayValue = displayValue;
    }

    public String getDisplay()
    {
        return displayValue;
    }
}

This allows you to put the Enum itself into your configuration, and iterate over all instances.

这允许您将 Enum 本身放入您的配置中,并遍历所有实例。

SimpleHash globalModel = new SimpleHash();
TemplateHashModel enumModels = BeansWrapper.getDefaultInstance().getEnumModels();
TemplateHashModel myEnumModel = (TemplateHashModel) enumModels.get("your.fully.qualified.enum.MyEnum");

globalModel.put("MyEnum", myEnumModel);
freemarkerConfiguration.setAllSharedVariables(globalModel);

Then you can iterate over the enum,

然后你可以遍历枚举,

<#list MyEnum?values as item>
    ${item.display}
</#list> 

回答by ddekany

The accepted answer isn't the simplest solution since 2.3.22. While myMap[key]still assumes a string key (see FAQ entry why), now one can use myMap?api.get(key)as a workaround. It needs some configuring though:

自 2.3.22 以来,接受的答案并不是最简单的解决方案。虽然myMap[key]仍然假设一个字符串键(请参阅 FAQ 条目为什么),但现在可以myMap?api.get(key)用作一种解决方法。不过它需要一些配置:

  • First of all, ?apiis disallowed by default, so you need to set the api_builtin_enabled(Configuration.setAPIBuiltinEnabled(boolean)) setting to true.
  • Then, the object_wrapper(Configuration.setObjectWrapper(ObjectWrapper)) used needs to support this feature (exposing the API). If you don't set the object_wrapperanywhere, then just increasing the incompatible_improvementssetting (the Configurationconstructor parameter, or Configuration.setIncompatibleImprovements(Version)) to 2.3.22 solves this. If you set the object_wrapper(i.e., you overwrite the default), and it's a DefaultObjectWrapperinstance, then note that DefaultObjectWrapperhas its own incompatibleImprovementsproperty that has to be set to 2.3.22. If you are using pure BeansWrapper(not recommended!) then you have to do nothing, as it always supports this feature.
  • 首先,?api默认情况下是不允许的,因此您需要将api_builtin_enabled( Configuration.setAPIBuiltinEnabled(boolean)) 设置设置为true
  • 那么,使用的object_wrapper( Configuration.setObjectWrapper(ObjectWrapper)) 需要支持这个特性(暴露 API)。如果您没有设置object_wrapper任何地方,那么只需将incompatible_improvements设置(Configuration构造函数参数或Configuration.setIncompatibleImprovements(Version))增加到 2.3.22 即可解决此问题。如果你设置了object_wrapper(即你覆盖了默认值),并且它是一个DefaultObjectWrapper实例,那么请注意它DefaultObjectWrapper有自己的incompatibleImprovements属性,必须设置为 2.3.22。如果您使用 pure BeansWrapper(不推荐!),那么您什么都不用做,因为它始终支持此功能。