仅比较 BigDecimal 列表与 long 列表,未返回任何结果。

huangapple go评论84阅读模式
英文:

nothing returned by comparing BigDecimal list to long list

问题

以下是翻译后的内容:

我有一个 BigDecimal 的列表,以及一个具有长整型字段的实体列表,我想要添加任何其长整型属性包含在 BigDecimal 列表中的实体。
我不知道发生了什么,我得到了一个空列表。

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;
}
英文:

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&lt;Utilisateur&gt; signataireUsersOfDoc (List&lt;BigDecimal&gt; list) {
    List &lt;Utilisateur&gt; filledList = utilisateurDAO.findAll();
	List &lt;Utilisateur&gt; filteredList = new ArrayList&lt;Utilisateur&gt;() ;
	BigDecimal n;
		
    for (Utilisateur temp : filledList) {
        n = new BigDecimal(temp.getPoste().getIdPoste());
        if (list.contains(n)) {
	        filteredList.add(temp) ;
        }
     }
     return filteredList; 
}

答案1

得分: 2

调用List#contains时,会在每个对象上调用equals方法,尝试找到匹配项(直到找到为止)。

问题在于,BigDecimal类的equals方法存在问题,具体来说:

> 将此 BigDecimal 与指定的对象进行比较以实现相等性。
> 与 compareTo 不同,此方法仅在两个 BigDecimal 对象的值和标度相等时才将其视为相等
> (因此,通过此方法比较时,2.0 与 2.00 不相等)。

这可能会引起许多问题。

由于您使用的是Java 7,并且无法使用流(streams),因此可以创建一个辅助方法(以保持代码整洁),该方法将通过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;
}

(代码部分未翻译)

英文:

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&lt;BigDecimal&gt; list, BigDecimal value) {
    for (BigDecimal item : list) {
        if (item.compareTo(value) == 0) {
            return true;
        }
    }
    
    return false;
}

public List&lt;Utilisateur&gt; signataireUsersOfDoc (List&lt;BigDecimal&gt; list) {
    List &lt;Utilisateur&gt; filledList = utilisateurDAO.findAll();
    List &lt;Utilisateur&gt; filteredList = new ArrayList&lt;Utilisateur&gt;() ;
    BigDecimal n;
        
    for (Utilisateur temp : filledList) {
        n = new BigDecimal(temp.getPoste().getIdPoste());
        if (listContains(list, n)) {
            filteredList.add(temp) ;
        }
     }
     return filteredList; 
}

答案2

得分: 0

The problem of BigDecimal.equals is:

比较此 BigDecimal 与指定的对象是否相等。与 compareTo 不同,此方法仅在两个 BigDecimal 对象的值和标度相等时才认为它们相等(因此,通过此方法比较时,2.0 不等于 2.00)。

因此,100 和 100.00 是不同的。

Andy 的答案已经指出了这一点。

而且,由于 List.contains 本身已经比较慢,可以使用一个 Set<Long>

public List<Utilisateur> signataireUsersOfDoc(List<BigDecimal> list) {
    Set<Long> set = list.stream().map(bd -> bd.longValue()).collect(Collectors.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(Collectors.toSet());

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

(伪代码)

英文:

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&lt;Long&gt;:

public List&lt;Utilisateur&gt; signataireUsersOfDoc (List&lt;BigDecimal&gt; list) {
    Set&lt;Long&gt; set = list.stream().map(bd -&gt; bd.longValue()).collect(Collect.toSet());

    List &lt;Utilisateur&gt; filledList = utilisateurDAO.findAll();
    List &lt;Utilisateur&gt; filteredList = new ArrayList&lt;Utilisateur&gt;() ;
    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&lt;Long&gt; set = list.stream().map(bd -&gt; bd.longValue()).collect(Collect.toSet());

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

(Pseudo-code)

huangapple
  • 本文由 发表于 2020年8月26日 21:36:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/63598887.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定