英文:
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<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;
}
答案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<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;
}
答案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<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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论