问题描述
我有一个BigDecimal
列表和一个具有长字段的实体的列表,我想添加BigDecimal
列表中包含其long属性的任何实体。
我不知道发生了什么,我得到了一个空名单。
public List<Utilisateur> signataireUsersOfDoc (List<BigDecimal> list) {
List <Utilisateur> filledList = utilisateurDAO.findAll();
List <Utilisateur> filteredList = new ArrayList<Utilisateur>() ;
BigDecimal n;
for (Utilisateur temp : filledList) {
n = new BigDecimal(temp.getPoste().getIdPoste());
if (list.contains(n)) {
filteredList.add(temp) ;
}
}
return filteredList;
}
解决方法
调用List#contains
时,将在每个对象上调用equals
方法,试图找到一个匹配项(直到找到一个匹配项)。
问题在于,BigDecimal
类的equals
方法存在问题,即:
将此BigDecimal与指定的Object比较是否相等。 与compareTo不同,此方法认为两个BigDecimal对象相等 仅当它们的值和规模相等时(因此2.0不等于 用这种方法比较时为2.00。
会引起很多头痛。
由于您使用的是Java7并且无权访问流,因此请创建一个辅助方法(以保持代码干净),该方法将通过BigDecimal#compareTo
方法比较该值,并使用该方法代替直接List#contains
呼叫:
private static boolean listContains(List<BigDecimal> list,BigDecimal value) {
for (BigDecimal item : list) {
if (item.compareTo(value) == 0) {
return true;
}
}
return false;
}
public List<Utilisateur> signataireUsersOfDoc (List<BigDecimal> list) {
List <Utilisateur> filledList = utilisateurDAO.findAll();
List <Utilisateur> filteredList = new ArrayList<Utilisateur>() ;
BigDecimal n;
for (Utilisateur temp : filledList) {
n = new BigDecimal(temp.getPoste().getIdPoste());
if (listContains(list,n)) {
filteredList.add(temp) ;
}
}
return filteredList;
}
,
BigDecimal.equals
的问题是:
将此BigDecimal与指定的Object比较是否相等。与compareTo不同,此方法仅在两个BigDecimal对象的值和比例相等时才认为它们相等(由此方法比较,因此2.0不等于2.00)。
因此100和100.00不同。
安迪的答案已经指出了这一点。
由于List.contains
总是很慢,因此请使用Set<Long>
:
public List<Utilisateur> signataireUsersOfDoc (List<BigDecimal> list) {
Set<Long> set = list.stream().map(bd -> bd.longValue()).collect(Collect.toSet());
List <Utilisateur> filledList = utilisateurDAO.findAll();
List <Utilisateur> filteredList = new ArrayList<Utilisateur>() ;
for (Utilisateur temp : filledList) {
long n = temp.getPoste().getIdPoste();
if (set.contains(n)) {
filteredList.add(temp) ;
}
}
return filteredList;
}
然而,真正的解决方案是:
Set<Long> set = list.stream().map(bd -> bd.longValue()).collect(Collect.toSet());
return utilisateurDAO.findWhere(CriteriaBuilder.idPoste.in(set));
(伪代码)