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

但是,重复项不会从列表中删除,当我不想重复时,它们会保留下来。

最佳答案

问题编辑

在聊天中交谈后,必须考虑其他参数:


  • 的倍数Prospect可以具有相同的prospect number,但它们在数据库中确实具有唯一的主键。因此,重复过滤器不能依赖Prospect等式
  • Prospect具有已访问状态,该状态定义了公司是否已联系Prospect。两种主要状态是NEWMETProspect只能是一个MET。其他重复项(具有相同的prospect number)只能是NEW


  • 算法

    该问题需要另外解决一个步骤:
  • 前景需要按prospect number分组。在这一阶段,我们将进行<ProspectNumber, List<Prospect>>映射。但是,List<Prospect>必须根据早期
  • 定义的规则以单个元素结尾
  • 在列表中,如果未满足潜在客户,则找到另一个具有满足状态的潜在客户,则第一个潜在客户将被丢弃

  • 因此,将使用以下规则生成列表:
  • 如果潜在客户在潜在客户编号方面没有重复,则保留该状态,而不考虑其状态
  • 如果某个潜在客户的潜在客户编号重复,则仅保留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()实际上返回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);
    


    供您参考,如果两个具有相同ProspectionProspectNumber相等,那么一个简单的 distinct() 就足够了:
    List<Prospection> all = prospectionRepository.findAll()
            .stream()
            .distinct()
            .collect(Collectors.toList());
    prospectionRepository.save(all);
    

    07-24 09:45