简体   繁体   中英

nothing returned by comparing BigDecimal list to long list

I have a list of BigDecimal , and a list of the entity which have a long field, I want to add any entity that it's long attribute contained in the BigDecimal list. I don't know what's happening, I get an empty list.

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; 
}

When calling List#contains , the equals method is called on each object, trying to find a match (until one is found).

The problem is, the equals method of the BigDecimal class is problematic, namely:

Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).

which can cause a lot of headache.

Since you're using Java7 and don't have access to streams, create a helper method (to keep your code clean), which will compare the value by the BigDecimal#compareTo method and use that one in place of direct List#contains call:

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; 
}

The problem of BigDecimal.equals is:

Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).

Hence 100 and 100.00 are different.

The answer of Andy already pointed this out.

And as a List.contains is slow anyways, use a 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; 
}

The real solution would however be something like:

    Set<Long> set = list.stream().map(bd -> bd.longValue()).collect(Collect.toSet());

    return utilisateurDAO.findWhere(CriteriaBuilder.idPoste.in(set));

(Pseudo-code)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM