在我的Entity类中,我有一个HashMap。现在我正在尝试创建一个选择此地图,以便能够选择对象。所以我创建了以下类:
HorseConverter:
@Named
public class HorseConverter implements Converter{
@EJB
private HorseBean bean;
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return bean.getHorse(Long.valueOf(value));
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if(!(value instanceof Horse)){
throw new ConverterException(new FacesMessage("Object is not a Horse"));
} else {
Horse h = (Horse) value;
return Long.toString(h.getId());
}
}
}
种族实体:
public Map<Horse, Integer> getHorses() {
return horses;
}
public void setHorses(HashMap<Horse, Integer> horses) {
this.horses = horses;
}
我的观点:
Horse:
<h:selectOneMenu value="#{betController.horse}" converter="#{horseConverter}">
<f:selectItems value="#{raceController.selectedRace.horses}" var="h" itemLabel="#{h.nickName}" itemValue="#{h}"/>
</h:selectOneMenu>
似乎我得到的价值不是马的一个实例。我检查了以下链接: https://stackoverflow.com/tags/selectonemenu/info因此,密钥似乎被自动用作值。但即使编写h.key也没有什么区别。
编辑: 这是来自Horse Entity的哈希和等于代码:
@Override
public int hashCode() {
int hash = 7;
hash = 97 * hash + (int) (this.id ^ (this.id >>> 32));
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Horse other = (Horse) obj;
if (this.id != other.id) {
return false;
}
return true;
}
答案 0 :(得分:0)
你有没有在Horse()对象中覆盖hashcode()和equals()?
你的转换器需要equals()覆盖才能工作。如果不这样做,只有两个对同一个Horse()实例的引用将是相同的,而不是两个具有完全相同状态的单独实例。集合创建一个隐式副本进行比较,因此在这种情况下,您不会在堆上有单个实例。
不要忘记equals()对象中的参数是Object(),而不是Horse()。
如果不覆盖hashcode(),则每个Horse实例的哈希码都不同。这意味着你很难找到合适的马进行比较,即使你的马在逻辑上是等价的,因为你将会有多个实例,你将比较你的HashMap中的马。
有关详细信息,请参阅Effective Java by Joshua Bloch的本章。
答案 1 :(得分:0)
您无法在var
值上使用Map
。只有当您使用<f:selectItems>
而不是List<Horse>
时,此特定Map<Horse, Integer>
构造才有效。
public List<Horse> getHorses() {
return horses;
}
如果你真的想使用Map
,那么你应该返回Map<String, Horse>
,其中String
是Horse
的昵称。
public Map<String, Horse> getHorses() {
return horses;
}
如果使用Map
值,请不要忘记删除var
:
<f:selectItems value="#{raceController.selectedRace.horses}" />
地图的键成为选项标签,地图的值成为选项值。
无关,HashMap
本质上是无序的。如果要按插入顺序显示下拉项,请使用LinkedHashMap
。