【问题标题】:Using java.util.Map in h:dataTable在 h:dataTable 中使用 java.util.Map
【发布时间】:2012-12-29 21:48:47
【问题描述】:

我需要使用<h:dataTable> 显示Map。我的支持 bean 有一个 Map 属性,如下所示:

public class Bean {

    private Map<Integer,String> map; // +getter

    @PostConstruct
    public void init() {
        map = new TreeMap<Integer,String>();
        map.put(1,"Sasi");
        map.put(2,"Pushparaju");
        map.put(3,"Venkat Raman");
        map.put(3,"Prabhakaran");
    }

}

然后在 JSF 页面中,我尝试将此 Map 属性绑定到 &lt;h:dataTable&gt;value 属性。

 <h:dataTable border="1" value="#{bean.map}" var="map">
    <h:column id="column1">
        <f:facet name="header">
            <h:outputText value="UserId"></h:outputText>
        </f:facet>
        <h:outputText value="#{map.getKey}"></h:outputText>
    </h:column>
    <h:column id="column2">
        <f:facet name="header">
            <h:outputText value="Email Id"></h:outputText>
        </f:facet>
        <h:outputText value="#{map.getValue}"></h:outputText>
    </h:column>
</h:dataTable>

错误提示 getKeygetValue 不存在。我可以理解这不是正确的方法。如何使用&lt;h:dataTable&gt; 呈现Map

【问题讨论】:

    标签: jsf datatable hashmap treemap


    【解决方案1】:

    在即将推出的 JSF 2.3 之前,UIData 组件(例如 &lt;h:dataTable&gt;&lt;p:dataTable&gt; 等)和 &lt;ui:repeat&gt;支持迭代 Map。这仅在 &lt;c:forEach&gt; 中受支持。

    一种方法是将映射条目转换为数组(单独的 entrySet() 将不起作用,因为 UIData 也不支持 Set,直到即将推出的 JSF 2.3)。

    <h:dataTable value="#{bean.map.entrySet().toArray()}" var="entry">
        <h:column>#{entry.key}</h:column>
        <h:column>#{entry.value}</h:column>
    </h:dataTable>
    

    另一种方法是将映射的条目集包装在&lt;h:dataTable&gt; 可以迭代的集合中,例如ArrayList

    public class Bean {
    
        private Map<Integer, String> map;
        private List<Entry<Integer, String>> entries; // +getter (no setter necessary)
    
        @PostConstruct
        public void init() {
            map = new TreeMap<>();
            map.put(1, "Sasi");
            map.put(2, "Pushparaju");
            map.put(3, "Venkat Raman");
            map.put(4, "Prabhakaran");
            entries = new ArrayList<>(map.entrySet());
        }
    
        // ...
    }
    
    <h:dataTable value="#{bean.entries}" var="entry">
        <h:column>#{entry.key}</h:column>
        <h:column>#{entry.value}</h:column>
    </h:dataTable>
    

    然而,更简洁、自我记录和可重用的是使用List&lt;User&gt;,其中User 类具有必要的属性idname

    public class Bean {
    
        private List<User> users; // +getter (no setter necessary)
    
        @PostConstruct
        public void init() {
            users = new ArrayList<>();
            users.add(new User(1, "Sasi"));
            users.add(new User(2, "Pushparaju"));
            users.add(new User(3, "Venkat Raman"));
            users.add(new User(4, "Prabhakaran"));
        }
    
        // ...
    }
    
    <h:dataTable value="#{bean.users}" var="user">
        <h:column>#{user.id}</h:column>
        <h:column>#{user.name}</h:column>
    </h:dataTable>
    

    【讨论】:

    • 嗨 BalusC..,Entry 是非 Serializable 接口。使用ViewScoped Bean 时不影响。 [p.s 我正在使用LinkedHashMap]?
    • @KishorP:不。对于未来不相关的问题和/或更详细的答案,请按“”按钮。
    【解决方案2】:

    你也可以试试这个替代方案。

    <h:dataTable border="1" value="#{myBean.map.keySet().toArray()}" var="myVar">
        <h:column id="column1">
            <f:facet name="header">
                <h:outputText value="UserId"></h:outputText>
            </f:facet>
                <h:outputText value="#{myVar}"></h:outputText>
        </h:column>
        <h:column id="column2">
            <f:facet name="header">
                <h:outputText value="Email Id"></h:outputText>
            </f:facet>
                <h:outputText value="#{myBean.map.get(myVar)}"></h:outputText>
        </h:column>
    </h:dataTable>
    

    【讨论】:

    • 这是非常低效的性能。 value 属性中的 EL 表达式在每个迭代轮次中进行评估。因此,在每一轮迭代中都会读取映射键集并将其转换为数组。而且,map.get(key) 不必要地在地图上进行第二次迭代以获得值。因此,您在每次迭代期间执行的迭代中有一个嵌套迭代!您至少应该改用map.entrySet(),并且最好将其包装在一个固定的数组列表中。与当前接受的答案完全相同。
    【解决方案3】:

    关于 prageeth 的最后一个答案,您可以使用 entrySet 而不是 keySet;那么你就可以摆脱 myBean.map.get 了。看这个例子:

    <h:dataTable border="1" value="#{myBean.map.entrySet().toArray()}" var="map">
    <h:column id="column1">
        <f:facet name="header">
            <h:outputText value="UserId"></h:outputText>
        </f:facet>
            <h:outputText value="#{map.key}"></h:outputText>
    </h:column>
    <h:column id="column2">
        <f:facet name="header">
            <h:outputText value="Email Id"></h:outputText>
        </f:facet>
            <h:outputText value="#{map.value}"></h:outputText>
    </h:column>
    </h:dataTable>
    

    这适用于 myfaces 2.2.3,因为我自己刚刚使用过。

    注:我最好把上个帖子评论一下,但我的声誉不够高,所以这是一个额外的答案。

    【讨论】:

      猜你喜欢
      • 2016-10-26
      • 2012-06-16
      • 1970-01-01
      • 2015-04-11
      • 2012-07-22
      • 1970-01-01
      • 2015-08-07
      相关资源
      最近更新 更多