我必须从从 CrudRepository 检索到的对象列表中删除重复项。
我做到了:
if (!prospectionRepository.findAll().isEmpty()) {
List<Prospection> all = prospectionRepository.findAll();
for (int i = 0; i < all.size()-1; i++) {
for (int k = i+1;k < all.size(); k++) {
if (all.get(i).getProspectNumber() == all.get(k).getProspectNumber()) {
all.remove(all.get(i));
}
}
}
prospectionRepository.save(all);
}
但是,不会从列表中删除重复项,然后在我不想的时候保留它们。
最佳答案
问题编辑
在聊天对话之后,必须考虑额外的参数:
- multiples
Prospect
may have the sameprospect number
but they do have an unique primary key in the database. Consequently, the duplicate filter cannot rely on theProspect
equality- a
Prospect
has a visited status which defined whether theProspect
has been contacted by the company or not. The two main status areNEW
andMET
. Only oneProspect
can beMET
. Other duplicates (with the sameprospect number
) can only beNEW
算法
问题需要额外的步骤才能解决:
- 潜在客户需要按
prospect number
分组.在这个阶段,我们将<ProspectNumber, List<Prospect>>
映射。然而,List<Prospect>
必须根据前面定义的规则以单个元素结束 - 在列表中,如果未满足潜在客户并且发现另一个具有满足状态的潜在客户,则第一个潜在客户将被丢弃
因此,列表将按照以下规则生成:
- 如果潜在客户在潜在客户编号方面没有重复项,则无论其状态如何都将保留
- 如果潜在客户在潜在客户编号方面有重复,则只有
met
一个被保留 - 如果多个潜在客户具有相同的潜在客户编号但没有一个是
met
,然后满足任意一个:Stream
不保证按列表顺序循环。
代码
诀窍是通过 Map
因为 key 将保持唯一性。如果您的预期号码是特定类型,这将假定 equals()
和 hashCode()
被正确定义。
免责声明:代码未经测试
List<Prospection> all = prospectionRepository.findAll().stream()
// we instantiate here a Map<ProspectNumber, Prospect>
// There is no need to have a Map<ProspectNumber, List<Propect>>
// as the merge function will do the sorting for us
.collect(Collectors.toMap(
// Key: use the prospect number
prospect -> prospect.getProspectNumber(),
// Value: use the propect object itself
prospect -> prospect,
// Merge function: two prospects with the same prospect number
// are found: keep the one with the MET status or the first one
(oldProspect, newProspect) -> {
if(oldProspect.getStatus() == MET){
return oldProspect;
} else if (newProspect.getStatus() == MET){
return newProspect;
} else{
// return the first one, arbitrary decision
return oldProspect;
}
}
))
// get map values only
.values()
// stream it in order to collect its as a List
.stream()
.collect(Collectors.toList());
prospectionRepository.save(all);
Map.values()
实际上返回一个 Collection
.所以如果你的 prospectionRepository.save(...)
可以接受 Collection
(不仅是 List
),你可以走得更快。我还使用以下同义词:
- static method reference :
Prospect::getProspectNumber
是Function
相当于prospect -> prospect.getProspectNumber()
-
Function.identity()
:相当于prospect -> prospect
- 三元运算符:它返回相同的东西但写法不同
Collection<Prospection> all = prospectionRepository.findAll().stream()
.collect(Collectors.toMap(
Prospect::getProspectNumber,
Function.identity(),
(oldProspect, newProspect) -> newProspect.getStatus() == MET ? newProspect : oldProspect
)).values();
prospectionRepository.save(all);
<子>
供您引用,如果两个 Prospection
具有相同的ProspectNumber
是相等的,那么一个简单的 distinct()
就足够了:
List<Prospection> all = prospectionRepository.findAll()
.stream()
.distinct()
.collect(Collectors.toList());
prospectionRepository.save(all);
关于java - 比较来自 findAll() 的 java 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46715510/