比较BigDecimal列表和长列表不会返回任何结果

问题描述

我有一个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));

(伪代码)