2013-07-26 40 views
2

我有下面这段代码 -Freemarker的:遍历LinkedHashMap中

public class Result { 
    private Map<String, String> dataPoints = new LinkedHashMap<String, String>(); 

    public Map<String, String> getData() { 
     return Maps.newHashMap(data); 
    } 

    public Set<Map.Entry<String, String>> getDataEntries() { 
     return data.entrySet(); 
    } 

    public void addData(final String key, final String value) { 
     this.data.put(key, value); 
    } 
} 

我使用LinkedHashMap的,因为我想保持插入顺序。我试图在freemarker代码中迭代地图,如下所示。但是,我得到一个例外。

<#if (result.dataPoints?keys?size > 0) > 
    <#list result.getDataEntries() as entry> 
     <tr> 
      <td width="35%"> 
       <div>${entry.key}</div> 
      </td> 
      <td width="45%">${entry.value}</td> 
      <td width="19%">&nbsp;</td> 
     </tr> 
    </#list> 
</#if> 

例外:

Expression result.getDataEntries is undefined on line 50, column 24 in settings/settings- 
diagnostics.ftl. The problematic instruction: ---------- ==> list result.getDataEntries() 
as entry [on line 50, column 17 in settings/settings-diagnostics.ftl] in user-directive 
printDiagnosticResult [on line 64, column 25 in settings/settings-diagnostics.ftl] in 
user-directive printDiagnosticResult [on line 76, column 13 in settings/settings- 
diagnostics.ftl] in user-directive layout.landingbase [on line 1, column 1 in  
settings/settings-diagnostics.ftl] ---------- Java backtrace for programmers: ---------- 
freemarker.core.InvalidReferenceException: Expression result.getDataEntries is undefined 
on line 50, column 24 in settings/settings-diagnostics.ftl. at 
freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:124) at 
freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:134) at 
freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:114) at  
freemarker.core.Expression.getAsTemplateModel(Expression.java:89) at 
freemarker.core.IteratorBlock.accept(IteratorBlock.java:94) at  
freemarker.core.Environment.visit(Environment.java:208) at 

如果我替换上面代码:

<#if (result.dataPoints?keys?size > 0) > 
    <#list result.dataPoints?keys as key> 
     <tr> 
      <td width="35%"> 
       <div>${key}</div> 
      </td> 
      <td width="45%">${result.dataPoints[key]}</td> 
      <td width="19%">&nbsp;</td> 
     </tr> 
    </#list> 
</#if> 

任何想法,我怎么遍历在地图上,让我得到了相同的顺序?

+0

什么是与最后一个模板的问题? – ddekany

+0

@ddekany:'result.dataPoints?keys'返回的项目不按照插入操作排序。即使由'result.dataPoints?values'返回的项目也不符合插入顺序。 – devang

+1

它保持我的订单。 ''key'不会返回一些与键混合的方法或属性?因为那时我知道问题是什么...... – ddekany

回答

2

这应该做的伎俩:

<#if result.dataPoints?has_content > 
    <#list result.dataPoints.entrySet() as entry> 
     <tr> 
      <td width="35%"> 
       <div>${entry.key}</div> 
      </td> 
      <td width="45%">${entry.value}</td> 
      <td width="19%">&nbsp;</td> 
     </tr> 
    </#list> 
</#if> 

可能还需要设置对象包装程序freemarker模板配置。就像这样:

BeansWrapper beansWrapper = (BeansWrapper) ObjectWrapper.BEANS_WRAPPER; 
beansWrapper.setExposeFields(true); 
config.setObjectWrapper(beansWrapper); 

哪里configfreemarker.template.Configuration。 如果您在使用Spring框架,然后扩展FreeMarkerConfigurer

public class FreeMarkerBeanWrapperConfigurer extends FreeMarkerConfigurer { 
    @Override 
    protected void postProcessConfiguration(Configuration config) throws IOException, TemplateException { 
    super.postProcessConfiguration(config); 

    BeansWrapper beansWrapper = (BeansWrapper) ObjectWrapper.BEANS_WRAPPER; 
    beansWrapper.setExposeFields(true); 
    config.setObjectWrapper(beansWrapper); 
    } 
} 
+1

同样,'?keys'意味着在LinkedHashMap的情况下以原始顺序返回键。我试过它是100%肯定的,它在这里工作。因此,尽管此解决方案可能有效,但最好找出问题的根源。 – ddekany

+0

@ddekany:我同意,我想我错过了一些东西。我试图找到根本原因。 – devang

+0

@gotuskar:如果没有实现'SortedMap',Maps会自动被freemarker包装到'SimpleHash'中。 'LinkedHashMap'没有实现'SortedMap'并且被包装到'HashMap'中。正如我所说的,你需要使用'BeansWrapper'来获得'LinkedHashMap'的所有好处。你可以在这里阅读更多关于freemarker SimpleHash:[SimpleHash](http://freemarker.org/docs/api/freemarker/template/SimpleHash.html) –