Znalezienie duplikatów używając hashmap.

0

Witam.

Mam program który ma kolekcje donatorów, pacjentów oraz listę zawierająca parę donator/pacjent.

Donatorów oraz pacjentów trzymam w hashMap, natomiast parę w arraylist.

 Map<String, Pacjent> mapaPacjentów = new HashMap<>();
 Map<String, Donator>   mapaDonatorów  = new HashMap<>();
 List<DonatorPacjentPara> listaDonatorPacjentPara = new ArrayList<>(); 

W tym programie, donator nie może być donatorem dla dwóch pacjentów.

 public List<DonatorPacjentPara> listaZduplikowanychDonatorów()
    {
        List<DonatorPacjentPara> rezultat = new ArrayList<>();                    
           
        for (DonatorPacjentPara donator : listaDonatorPacjentPara )
        {             
            for(DonatorPacjentPara inny: listaDonatorPacjentPara ){
                    Donator d = this.getDonatorPoprzezID(donator.getIdDonatora()); // Ta metoda zwraca donatora z mapy Donatorów.
                    Donator i = this.getDonatorPoprzezID(inny.getIdDonatora()); 

                    Pacjent pacjentDonatora = this.getPacjentPoprzezID(donor.getIdPacjenta());  // Ta metoda zwraca pacjenta z mapy Pacjentów. 
                    Pacjent pacjentInnego = this.getPacjentPoprzezID(inny.getIdPacjenta());


                    if (d.equals(i) && !pacjentDonatora .equals(pacjentInnego ))
                    {
                        rezultat .add(donor);
                        rezultat .add(other);
                    }                       
                }            
        }
        return rezultat ;
    }

Ta metoda zwraca 4 duplikaty (tyle właśnie musi być), jednak jej szybkość to o(n2). Muszę sprawić żeby ta metoda działała o wiele szybciej, Postanowiłem spróbować to zrobić, poprzez nadpisanie hasha oraz equals w klasie DonatorPacjentPara .

public class DonatorPacjentPara 
{
        protected String idPacjenta; 
        protected String idDonatora; 
        
        public DonatorPacjentPara ( String pacjent, String donator)
        {
           idPacjenta= pacjent; 
           idDonatora= donator; 
        }
        /**
         * @return the idPacjenta
         */
        public String getIdPacjenta()
        {
            return idPacjenta;
        }

        /**
         * @return the idDonatora
         */
        public String getIdDonatora()
        {
            return idDonatora;
        }

    @Override
    public String toString()
    {
        return "DonatorPacjentPara {" + "ID Pacjenta=" + idPacjenta+ ", ID Donatora=" + idDonatora+ '}';
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj){
            return true;
        }
        
        if(obj == null){
            return false;
        }
        
        if(getClass() != obj.getClass()){
            return false;
        }
        
        final DonatorPacjentPara inny = (DonatorPacjentPara )obj;      
       
            
        if(!(Objects.equals(this.idDonatora, inny.getIdDonatora())) && (Objects.equals(this.idPacjenta, inny.getIdPacjenta()))){
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + Objects.hashCode(this.idPacjenta+ this.idDonatora);
        return hash;
    }     
}

Następnie zmieniłem metodę do znalezienia z duplikowanych donatorów w ten sposób:

public List<DonatorPacjentPara > listaZduplikowanychDonatorów()
    {
        List<DonatorPacjentPara > rezultat = new ArrayList<>();          
        Map<DonatorPacjentPara , DonatorPacjentPara > mapaDonatorPara = new HashMap<>();
           
        for (DonatorPacjentPara donatorPacjent: linkTable){
                if(mapaDonatorPara .containsKey(donatorPacjent)){                
                         rezultat.add(donorMap.get(donatorPacjent));
                    }else{
                       mapaDonatorPara .put(donatorPacjent, donatorPacjent);
                    }
        }
        
        return rezultat ;
    }

Teoria tej metody jest taka, że robię kółko w okół wszystkich par donator/pacjentów. Następnie sprawdzam czy mapa już zawiera taką parę (tutaj metoda equals miała sprawdzić czy donator ma więcej niż 1 pacjenta) , i jeśli tak, duplikat zostaje dodany do listy. Jeśli nie, dodaję parę do lokalnej mapy.

Niestety nie działa. Przyznam że pierwszy raz próbuję użyć mapy w ten sposób, i chyba jednak nie za bardzo jeszcze rozumiem jak to dokładnie powinno działać

0

mapaDonatorPara .put(donatorPacjent, donatorPacjent);

Jaki jest sens mapować X na X? Może lepiej użyć wtedy HashSet?
Standardowo się rozwiązuje to tak: pobierasz z mapy, jeżeli jest null to jest to pierwsze wystąpienie i wpisujesz do mapy, jeżeli nie jest null to obsługujesz duplikat.
Alternatywnym sposobem rozwiązania tego problemu jest utworzenie mapy obiekt -> liczba wystąpień obiektu. Przy każdym napotkaniu obiektu zwiększasz o jeden przypisaną mu liczbę wystąpień (ponowne wpisanie do mapy, pamiętaj o zmianie nulla na 1).

1 użytkowników online, w tym zalogowanych: 0, gości: 1