比较来自 findAll() 的 java 元素

compare java element from a findAll()

我必须从从 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);
}

但是,不会从列表中删除重复项,然后在我不想删除时保留它们。

为什么不使用以 prospectNumber 作为值的 HashSet。 HashSet 不能包含重复的键。之后,您可以遍历 List 并删除所有重复元素。希望对您有所帮助!

你可以使用像

这样的东西
List<Prospection> all = prospectionRepository.findAll();
Set<Object> prospectNumbers = new HashSet<Object>();
Iterator<Prospection> it = all.iterator();
while (it.hasNext()) {
    Prospection item = iterator.next();
    Object itemNumer = item.getProspectNumber();
    if (prospectNumbers.contains(itemNumber)) {
        it.remove();
    } else {
        prospectNumbers.add(itemNumber);
    }
}

问题编辑

在聊天中对话后,必须考虑其他参数:

  1. multiples Prospect may have the same prospect number but they do have an unique primary key in the database. Consequently, the duplicate filter cannot rely on the Prospect equality
  2. a Prospect has a visited status which defined whether the Prospect has been contacted by the company or not. The two main status are NEW and MET. Only one Prospect can be MET. Other duplicates (with the same prospect number) can only be NEW

算法

问题需要额外的步骤才能解决:

  1. 潜在客户需要按 prospect number 分组。在此阶段,我们将进行 <ProspectNumber, List<Prospect>> 映射。但是,List<Prospect> 必须根据之前定义的规则以单个元素结尾
  2. 在列表中,如果未满足潜在客户 AND 发现另一个具有 met 状态的潜在客户,则第一个潜在客户将被丢弃

因此,将按照以下规则生成列表:

  • 如果潜在客户在潜在客户编号方面没有重复,则无论其状态如何都将保留
  • 如果潜在客户的潜在客户编号重复,则只保留 met
  • 如果多个前景相同的前景编号,但没有一个是met,则满足任意一个:Stream不保证按列表顺序循环。

代码

诀窍是通过 Map,因为密钥将保持唯一性。如果您的预期数字是特定类型,这将假定 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()其实return一个Collection。因此,如果您的 prospectionRepository.save(...) 可以接受 Collection(不仅是 List),您可以走得更快。我还使用以下同义词:

  • static method referenceProspect::getProspectNumberFunction 等同于 prospect -> prospect.getProspectNumber()
  • Function.identity():等价于prospect -> prospect
  • 三元运算符:return是同一个东西,只是写法不同
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);