function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Chris Voge 9Chris Voge 9 

Set contains duplicate elements

Hello,

We have an issue where a Set object contains duplicate elements,
but the elements contain the same hashCode. Isn't the hashCode the
determining factor when considering whether there are duplicate items
in a Set ?

The problem starts on line:
        o.Most_Recent_Lead__c = lead.Id;       (see below)

If I comment this line out , there is no issue.

We are then moving the Set object to a List object, expecting
it to have unique elements, then attempt to perform a Database.update.
When attempting this, we get
            Duplicate id in list: 0065B000002HyxqQAC
for ( Opportunity o : oppList ){
        if ( o.accountId != null ){
            Id contactId = someMap.get( o.AccountId );
            if ( contactId != null ){
                List<Leads__c> tmpLeads = someOtherMap.get( contactId );

                if ( tmpLeads != null ){
                    DateTime mostRecent;
                    Leads__c mostRecentLead;
                    for ( Leads__c lead : tmpLeads ){

                        lead.Opportunity__c = o.Id;                                                                                        
                        if ( mostRecent == null || lead.createdDate > mostRecent ){
                            mostRecent = lead.createdDate;
                            o.Most_Recent_Lead__c = lead.Id;
                        }

                        if(updateOppSet.contains(o)){
                            System.debug('Already contains opp'); 
                        } else {
                            updateOppSet.add( o );
                        }
                        System.debug('Hashcode: ' + updateOppSet.hashCode());     // Debugging purposes
                        for ( Opportunity o1 : updateOppSet){
                            System.debug('Hashcode for elm: ' + System.hashCode(o1));
                        }         
                    }   
                }
            }   
        }
    }
    List<Opportunity> updateOppList = new List<Opportunity>();
    updateOppList.addAll( updateOppSet );
    
    Database.Saveresult[] results = Database.update(updateOppList, false);

Wondering why this is happening and if anyone can offer suggestions.

Much appreciated
Chris
Best Answer chosen by Chris Voge 9
Amit Chaudhary 8Amit Chaudhary 8
I hope you was using the Set<Opportunity> not set<ID>.

Please try below code and let us know if that will help you
List<Opportunity> updateOppList = new List<Opportunity>();
	Set<ID> setOppID = new Set<Id>();
	
	for ( Opportunity o : oppList )
	{
        if ( o.accountId != null )
		{
            Id contactId = someMap.get( o.AccountId );
            if ( contactId != null ){
                List<Leads__c> tmpLeads = someOtherMap.get( contactId );

                if ( tmpLeads != null ){
                    DateTime mostRecent;
                    Leads__c mostRecentLead;
                    for ( Leads__c lead : tmpLeads ){

                        lead.Opportunity__c = o.Id;                                                                                        
                        if ( mostRecent == null || lead.createdDate > mostRecent ){
                            mostRecent = lead.createdDate;
                            o.Most_Recent_Lead__c = lead.Id;
                        }

                        if(setOppID.contains(o.id))
						{
                            System.debug('Already contains opp'); 
                        } else 
						{
                            setOppID.add(o.id );
							updateOppList.add(o);
                        }
                       // System.debug('Hashcode: ' + updateOppSet.hashCode());     // Debugging purposes
                        //for ( Opportunity o1 : updateOppSet){
                        //    System.debug('Hashcode for elm: ' + System.hashCode(o1));
                       // }         
                    }   
                }
            }   
        }
    }
	
    Database.Saveresult[] results = Database.update(updateOppList, false);

 

All Answers

Allan Hotchkiss 4Allan Hotchkiss 4
Hi Chris, just out of curiosity, move the for loop on line 24 down to just above the call to updateOppList.addAll on line 33.  Also, do a System.debug(o1.Id) to see if the Id is in more than one object in the set.  My guess is that the state of the Opportunity object, and therefore the hash-code, is changing and thus not getting caught in the updateOppSet.contains call in subsequent iterations.  You may be better off using a Set<Id> instead of Set<Opportunity> and using that to see if you've already added the record to updateOppList.  In addition, declare updateOppList as a method-scoped variable and add records to it right after checking Set<Id> to see if you've already added a record.
Amit Chaudhary 8Amit Chaudhary 8
I hope you was using the Set<Opportunity> not set<ID>.

Please try below code and let us know if that will help you
List<Opportunity> updateOppList = new List<Opportunity>();
	Set<ID> setOppID = new Set<Id>();
	
	for ( Opportunity o : oppList )
	{
        if ( o.accountId != null )
		{
            Id contactId = someMap.get( o.AccountId );
            if ( contactId != null ){
                List<Leads__c> tmpLeads = someOtherMap.get( contactId );

                if ( tmpLeads != null ){
                    DateTime mostRecent;
                    Leads__c mostRecentLead;
                    for ( Leads__c lead : tmpLeads ){

                        lead.Opportunity__c = o.Id;                                                                                        
                        if ( mostRecent == null || lead.createdDate > mostRecent ){
                            mostRecent = lead.createdDate;
                            o.Most_Recent_Lead__c = lead.Id;
                        }

                        if(setOppID.contains(o.id))
						{
                            System.debug('Already contains opp'); 
                        } else 
						{
                            setOppID.add(o.id );
							updateOppList.add(o);
                        }
                       // System.debug('Hashcode: ' + updateOppSet.hashCode());     // Debugging purposes
                        //for ( Opportunity o1 : updateOppSet){
                        //    System.debug('Hashcode for elm: ' + System.hashCode(o1));
                       // }         
                    }   
                }
            }   
        }
    }
	
    Database.Saveresult[] results = Database.update(updateOppList, false);

 
This was selected as the best answer
Chris Voge 9Chris Voge 9
Was leaning towards changing to Set<ID> instead of Set<Opportunity>.
This should work well.

Thanks for the help all.
Chris