Duplicate class objects in a set
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
4
down vote
favorite
I am having 2 instances of a wrapper class holding the same values. Then I add both instances to a Set of that wrapper class and both instances are present in the set.
Say this is my code:
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
Now the priceBooksData
contains both instances of pbData
and pbData2
even though they have only 1 field name
and that field holds the same value.
Since these are not sObjects and don't hold Ids why are they not considered identical? Based on what? When I system.debug the value of pbData
and pbData2
what gets printed on the screen is identical.
apex set duplicate-value
add a comment |Â
up vote
4
down vote
favorite
I am having 2 instances of a wrapper class holding the same values. Then I add both instances to a Set of that wrapper class and both instances are present in the set.
Say this is my code:
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
Now the priceBooksData
contains both instances of pbData
and pbData2
even though they have only 1 field name
and that field holds the same value.
Since these are not sObjects and don't hold Ids why are they not considered identical? Based on what? When I system.debug the value of pbData
and pbData2
what gets printed on the screen is identical.
apex set duplicate-value
add a comment |Â
up vote
4
down vote
favorite
up vote
4
down vote
favorite
I am having 2 instances of a wrapper class holding the same values. Then I add both instances to a Set of that wrapper class and both instances are present in the set.
Say this is my code:
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
Now the priceBooksData
contains both instances of pbData
and pbData2
even though they have only 1 field name
and that field holds the same value.
Since these are not sObjects and don't hold Ids why are they not considered identical? Based on what? When I system.debug the value of pbData
and pbData2
what gets printed on the screen is identical.
apex set duplicate-value
I am having 2 instances of a wrapper class holding the same values. Then I add both instances to a Set of that wrapper class and both instances are present in the set.
Say this is my code:
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
Now the priceBooksData
contains both instances of pbData
and pbData2
even though they have only 1 field name
and that field holds the same value.
Since these are not sObjects and don't hold Ids why are they not considered identical? Based on what? When I system.debug the value of pbData
and pbData2
what gets printed on the screen is identical.
apex set duplicate-value
apex set duplicate-value
asked Aug 10 at 18:57
Arthlete
755515
755515
add a comment |Â
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
1
down vote
accepted
Making a small addition to your example will illustrate what's going on (or at least part of what's going on)
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
// We will see 2 individual entries in the set
system.debug(priceBooksData);
// The hashcodes will be different
system.debug(pbData.hashCode());
system.debug(pbData2.hashCode());
// And the equals method will return false
system.debug(pbData.equals(pbData2));
They're not identical based on the results of the equals()
and hashcode()
methods.
These two methods are used to both store and fetch data from maps and sets as mentioned in Using Custom Types in Map Keys and Sets
The base Object
class, from which every other SObject and Apex class inherit, contains a default implementation of these two methods. It's hard to say for sure what happens in this default implementation since there isn't much/any documentation on the Object
class in Apex, but given that Apex compiles to Java bytecode, I wouldn't think it a stretch to assume that we end up using the default Java implementation of hashcode()
.
Java's default hashcode()
takes into account the memory address that your object is stored in. Two different instances of the same class would be stored at different memory addresses, so their hashcode is different.
In the end, the fix here is to listen to the advice given in "Using Custom Types in Map Keys and Sets"
When using a custom type (your Apex class) for the map key or set elements, provide equals and hashCode methods in your class. Apex uses these two methods to determine equality and uniqueness of keys for your objects.
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about thehascode
andequals
methods.
â Arthlete
Aug 10 at 19:29
add a comment |Â
up vote
5
down vote
For any User defined type, you need to implement the equals
and hashCode
methods. Refer to the below excerpt from the documentation.
Uniqueness of set elements of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of all other non-primitive types is determined by comparing the objectsâ fields.
You will need to add these methods in your class, which should then look like something as below. Just make sure (more details here):
If two objects are equal, based on the equals method, hashCode must
return the same value.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceOf PricebookData)
return this.name == ((PricebookData) obj).name;
return false;
public Integer hashCode()
return (your logic of calculating hashcode);
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
add a comment |Â
up vote
1
down vote
Referring Using Custom Types in Map Keys and Sets, I could able to replicate this use case as follows:
Create equals()
and hashcode()
which returns Integer for comparison.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceof PricebookData)
PricebookData p = (PricebookData)obj;
return (name==p.name) ;
return false;
public Integer hashCode()
Integer chars = name.getChars();
Integer returnValueInt = 0;
for(integer i=0; i<chars.size();i++)
returnValueInt = returnValueInt + chars[i];
return (300 * returnValueInt);
Testing
PricebookData p1 = new PricebookData();
p1.name = 'Test';
PricebookData p2 = new PricebookData();
p2.name = 'Test1';
// Duplicate key
PricebookData p3 = new PricebookData();
p3.name = 'Test';
// Create a set
Set<PricebookData> s1 = new Set<PricebookData>();
s1.add(p1);
s1.add(p2);
s1.add(p3);
// Verify that we have only two elements
// since the p3 is equal to p1.
System.debug('final size=' + s1.size()); //this is 2.
1
Thank you, I really like yourhashCode
example!
â Arthlete
Aug 10 at 19:43
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Making a small addition to your example will illustrate what's going on (or at least part of what's going on)
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
// We will see 2 individual entries in the set
system.debug(priceBooksData);
// The hashcodes will be different
system.debug(pbData.hashCode());
system.debug(pbData2.hashCode());
// And the equals method will return false
system.debug(pbData.equals(pbData2));
They're not identical based on the results of the equals()
and hashcode()
methods.
These two methods are used to both store and fetch data from maps and sets as mentioned in Using Custom Types in Map Keys and Sets
The base Object
class, from which every other SObject and Apex class inherit, contains a default implementation of these two methods. It's hard to say for sure what happens in this default implementation since there isn't much/any documentation on the Object
class in Apex, but given that Apex compiles to Java bytecode, I wouldn't think it a stretch to assume that we end up using the default Java implementation of hashcode()
.
Java's default hashcode()
takes into account the memory address that your object is stored in. Two different instances of the same class would be stored at different memory addresses, so their hashcode is different.
In the end, the fix here is to listen to the advice given in "Using Custom Types in Map Keys and Sets"
When using a custom type (your Apex class) for the map key or set elements, provide equals and hashCode methods in your class. Apex uses these two methods to determine equality and uniqueness of keys for your objects.
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about thehascode
andequals
methods.
â Arthlete
Aug 10 at 19:29
add a comment |Â
up vote
1
down vote
accepted
Making a small addition to your example will illustrate what's going on (or at least part of what's going on)
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
// We will see 2 individual entries in the set
system.debug(priceBooksData);
// The hashcodes will be different
system.debug(pbData.hashCode());
system.debug(pbData2.hashCode());
// And the equals method will return false
system.debug(pbData.equals(pbData2));
They're not identical based on the results of the equals()
and hashcode()
methods.
These two methods are used to both store and fetch data from maps and sets as mentioned in Using Custom Types in Map Keys and Sets
The base Object
class, from which every other SObject and Apex class inherit, contains a default implementation of these two methods. It's hard to say for sure what happens in this default implementation since there isn't much/any documentation on the Object
class in Apex, but given that Apex compiles to Java bytecode, I wouldn't think it a stretch to assume that we end up using the default Java implementation of hashcode()
.
Java's default hashcode()
takes into account the memory address that your object is stored in. Two different instances of the same class would be stored at different memory addresses, so their hashcode is different.
In the end, the fix here is to listen to the advice given in "Using Custom Types in Map Keys and Sets"
When using a custom type (your Apex class) for the map key or set elements, provide equals and hashCode methods in your class. Apex uses these two methods to determine equality and uniqueness of keys for your objects.
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about thehascode
andequals
methods.
â Arthlete
Aug 10 at 19:29
add a comment |Â
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Making a small addition to your example will illustrate what's going on (or at least part of what's going on)
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
// We will see 2 individual entries in the set
system.debug(priceBooksData);
// The hashcodes will be different
system.debug(pbData.hashCode());
system.debug(pbData2.hashCode());
// And the equals method will return false
system.debug(pbData.equals(pbData2));
They're not identical based on the results of the equals()
and hashcode()
methods.
These two methods are used to both store and fetch data from maps and sets as mentioned in Using Custom Types in Map Keys and Sets
The base Object
class, from which every other SObject and Apex class inherit, contains a default implementation of these two methods. It's hard to say for sure what happens in this default implementation since there isn't much/any documentation on the Object
class in Apex, but given that Apex compiles to Java bytecode, I wouldn't think it a stretch to assume that we end up using the default Java implementation of hashcode()
.
Java's default hashcode()
takes into account the memory address that your object is stored in. Two different instances of the same class would be stored at different memory addresses, so their hashcode is different.
In the end, the fix here is to listen to the advice given in "Using Custom Types in Map Keys and Sets"
When using a custom type (your Apex class) for the map key or set elements, provide equals and hashCode methods in your class. Apex uses these two methods to determine equality and uniqueness of keys for your objects.
Making a small addition to your example will illustrate what's going on (or at least part of what's going on)
public class PricebookData
public String name;
Set<PricebookData> priceBooksData = new Set<PricebookData>();
PricebookData pbData = new PricebookData();
pbData.name = 'Test';
priceBooksData.add(pbData);
PricebookData pbData2 = new PricebookData();
pbData2.name = 'Test';
priceBooksData.add(pbData2);
// We will see 2 individual entries in the set
system.debug(priceBooksData);
// The hashcodes will be different
system.debug(pbData.hashCode());
system.debug(pbData2.hashCode());
// And the equals method will return false
system.debug(pbData.equals(pbData2));
They're not identical based on the results of the equals()
and hashcode()
methods.
These two methods are used to both store and fetch data from maps and sets as mentioned in Using Custom Types in Map Keys and Sets
The base Object
class, from which every other SObject and Apex class inherit, contains a default implementation of these two methods. It's hard to say for sure what happens in this default implementation since there isn't much/any documentation on the Object
class in Apex, but given that Apex compiles to Java bytecode, I wouldn't think it a stretch to assume that we end up using the default Java implementation of hashcode()
.
Java's default hashcode()
takes into account the memory address that your object is stored in. Two different instances of the same class would be stored at different memory addresses, so their hashcode is different.
In the end, the fix here is to listen to the advice given in "Using Custom Types in Map Keys and Sets"
When using a custom type (your Apex class) for the map key or set elements, provide equals and hashCode methods in your class. Apex uses these two methods to determine equality and uniqueness of keys for your objects.
edited Aug 10 at 19:29
answered Aug 10 at 19:25
Derek F
17.5k31344
17.5k31344
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about thehascode
andequals
methods.
â Arthlete
Aug 10 at 19:29
add a comment |Â
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about thehascode
andequals
methods.
â Arthlete
Aug 10 at 19:29
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about the
hascode
and equals
methods.â Arthlete
Aug 10 at 19:29
Great explanation, thank you! I assumed that there's something going on with the memory addresses but was completely oblivious about the
hascode
and equals
methods.â Arthlete
Aug 10 at 19:29
add a comment |Â
up vote
5
down vote
For any User defined type, you need to implement the equals
and hashCode
methods. Refer to the below excerpt from the documentation.
Uniqueness of set elements of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of all other non-primitive types is determined by comparing the objectsâ fields.
You will need to add these methods in your class, which should then look like something as below. Just make sure (more details here):
If two objects are equal, based on the equals method, hashCode must
return the same value.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceOf PricebookData)
return this.name == ((PricebookData) obj).name;
return false;
public Integer hashCode()
return (your logic of calculating hashcode);
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
add a comment |Â
up vote
5
down vote
For any User defined type, you need to implement the equals
and hashCode
methods. Refer to the below excerpt from the documentation.
Uniqueness of set elements of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of all other non-primitive types is determined by comparing the objectsâ fields.
You will need to add these methods in your class, which should then look like something as below. Just make sure (more details here):
If two objects are equal, based on the equals method, hashCode must
return the same value.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceOf PricebookData)
return this.name == ((PricebookData) obj).name;
return false;
public Integer hashCode()
return (your logic of calculating hashcode);
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
add a comment |Â
up vote
5
down vote
up vote
5
down vote
For any User defined type, you need to implement the equals
and hashCode
methods. Refer to the below excerpt from the documentation.
Uniqueness of set elements of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of all other non-primitive types is determined by comparing the objectsâ fields.
You will need to add these methods in your class, which should then look like something as below. Just make sure (more details here):
If two objects are equal, based on the equals method, hashCode must
return the same value.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceOf PricebookData)
return this.name == ((PricebookData) obj).name;
return false;
public Integer hashCode()
return (your logic of calculating hashcode);
For any User defined type, you need to implement the equals
and hashCode
methods. Refer to the below excerpt from the documentation.
Uniqueness of set elements of user-defined types is determined by the equals and hashCode methods, which you provide in your classes. Uniqueness of all other non-primitive types is determined by comparing the objectsâ fields.
You will need to add these methods in your class, which should then look like something as below. Just make sure (more details here):
If two objects are equal, based on the equals method, hashCode must
return the same value.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceOf PricebookData)
return this.name == ((PricebookData) obj).name;
return false;
public Integer hashCode()
return (your logic of calculating hashcode);
edited Aug 10 at 19:27
answered Aug 10 at 19:15
Jayant Das
6,2421319
6,2421319
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
add a comment |Â
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
Very interesting, thank you. I will give it a try right now!
â Arthlete
Aug 10 at 19:22
add a comment |Â
up vote
1
down vote
Referring Using Custom Types in Map Keys and Sets, I could able to replicate this use case as follows:
Create equals()
and hashcode()
which returns Integer for comparison.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceof PricebookData)
PricebookData p = (PricebookData)obj;
return (name==p.name) ;
return false;
public Integer hashCode()
Integer chars = name.getChars();
Integer returnValueInt = 0;
for(integer i=0; i<chars.size();i++)
returnValueInt = returnValueInt + chars[i];
return (300 * returnValueInt);
Testing
PricebookData p1 = new PricebookData();
p1.name = 'Test';
PricebookData p2 = new PricebookData();
p2.name = 'Test1';
// Duplicate key
PricebookData p3 = new PricebookData();
p3.name = 'Test';
// Create a set
Set<PricebookData> s1 = new Set<PricebookData>();
s1.add(p1);
s1.add(p2);
s1.add(p3);
// Verify that we have only two elements
// since the p3 is equal to p1.
System.debug('final size=' + s1.size()); //this is 2.
1
Thank you, I really like yourhashCode
example!
â Arthlete
Aug 10 at 19:43
add a comment |Â
up vote
1
down vote
Referring Using Custom Types in Map Keys and Sets, I could able to replicate this use case as follows:
Create equals()
and hashcode()
which returns Integer for comparison.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceof PricebookData)
PricebookData p = (PricebookData)obj;
return (name==p.name) ;
return false;
public Integer hashCode()
Integer chars = name.getChars();
Integer returnValueInt = 0;
for(integer i=0; i<chars.size();i++)
returnValueInt = returnValueInt + chars[i];
return (300 * returnValueInt);
Testing
PricebookData p1 = new PricebookData();
p1.name = 'Test';
PricebookData p2 = new PricebookData();
p2.name = 'Test1';
// Duplicate key
PricebookData p3 = new PricebookData();
p3.name = 'Test';
// Create a set
Set<PricebookData> s1 = new Set<PricebookData>();
s1.add(p1);
s1.add(p2);
s1.add(p3);
// Verify that we have only two elements
// since the p3 is equal to p1.
System.debug('final size=' + s1.size()); //this is 2.
1
Thank you, I really like yourhashCode
example!
â Arthlete
Aug 10 at 19:43
add a comment |Â
up vote
1
down vote
up vote
1
down vote
Referring Using Custom Types in Map Keys and Sets, I could able to replicate this use case as follows:
Create equals()
and hashcode()
which returns Integer for comparison.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceof PricebookData)
PricebookData p = (PricebookData)obj;
return (name==p.name) ;
return false;
public Integer hashCode()
Integer chars = name.getChars();
Integer returnValueInt = 0;
for(integer i=0; i<chars.size();i++)
returnValueInt = returnValueInt + chars[i];
return (300 * returnValueInt);
Testing
PricebookData p1 = new PricebookData();
p1.name = 'Test';
PricebookData p2 = new PricebookData();
p2.name = 'Test1';
// Duplicate key
PricebookData p3 = new PricebookData();
p3.name = 'Test';
// Create a set
Set<PricebookData> s1 = new Set<PricebookData>();
s1.add(p1);
s1.add(p2);
s1.add(p3);
// Verify that we have only two elements
// since the p3 is equal to p1.
System.debug('final size=' + s1.size()); //this is 2.
Referring Using Custom Types in Map Keys and Sets, I could able to replicate this use case as follows:
Create equals()
and hashcode()
which returns Integer for comparison.
public class PricebookData
public String name;
public Boolean equals(Object obj)
if (obj instanceof PricebookData)
PricebookData p = (PricebookData)obj;
return (name==p.name) ;
return false;
public Integer hashCode()
Integer chars = name.getChars();
Integer returnValueInt = 0;
for(integer i=0; i<chars.size();i++)
returnValueInt = returnValueInt + chars[i];
return (300 * returnValueInt);
Testing
PricebookData p1 = new PricebookData();
p1.name = 'Test';
PricebookData p2 = new PricebookData();
p2.name = 'Test1';
// Duplicate key
PricebookData p3 = new PricebookData();
p3.name = 'Test';
// Create a set
Set<PricebookData> s1 = new Set<PricebookData>();
s1.add(p1);
s1.add(p2);
s1.add(p3);
// Verify that we have only two elements
// since the p3 is equal to p1.
System.debug('final size=' + s1.size()); //this is 2.
answered Aug 10 at 19:30
Santanu Boral
28.5k52048
28.5k52048
1
Thank you, I really like yourhashCode
example!
â Arthlete
Aug 10 at 19:43
add a comment |Â
1
Thank you, I really like yourhashCode
example!
â Arthlete
Aug 10 at 19:43
1
1
Thank you, I really like your
hashCode
example!â Arthlete
Aug 10 at 19:43
Thank you, I really like your
hashCode
example!â Arthlete
Aug 10 at 19:43
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f228523%2fduplicate-class-objects-in-a-set%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password