public static void main(String[] args) {
HashSet set = new HashSet();
set.add(new StringBuffer("abc"));
set.add(new StringBuffer("abc"));
set.add(new StringBuffer("abc"));
set.add(new StringBuffer("abc"));
System.out.println(set);
}
Output:
[abc,abc,abc,abc]
Here in above code I added object of StringBuffer("abc")
many times and Set
adds it but Set never adds duplicates.
The meaning of "sets do not allow duplicate values" is that when you add a duplicate to a set, the duplicate is ignored, and the set remains unchanged. This does not lead to compile or runtime errors: duplicates are silently ignored. Set is implemented like that to avoid duplication.
A Set is a Collection that cannot contain duplicate elements. It models the mathematical set abstraction. The Set interface contains only methods inherited from Collection and adds the restriction that duplicate elements are prohibited.
Yes, you can but as the above answers state, you must write a Comparator. But the real question is why would you want to? The purpose of a StringBuffer is to modify the state while creating a string. Since it is a key in your SortedMap you shouldn't be modifying the key, so there is no point in saving the StringBuffer.
Duplicates: HashSet doesn't allow duplicate values. HashMap stores key, value pairs and it does not allow duplicate keys.
StringBuffer
does not override Object#equals()
and Object#hashCode()
, so identity of StringBuffer
instances is based not on the contents of the buffer, but by the object's address in memory.*
* That identity is based on an address in memory is not strictly required by the JLS, but is a consequence of a typical Object#hashCode()
implementation. From the JavaDoc:
As much as is reasonably practical, the hashCode method defined by class
Object
does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java™ programming language.)
StringBuffer
doesn't override either equals
or hashCode
- so each object is only equal to itself.
This makes sense as StringBuffer
is very much "mutable by design" - and equality can cause problems when two mutable objects are equal to each other, as one can then change. Using mutable objects as keys in a map or part of a set can cause problems. If you mutate one after insertion into the collection, that invalidates the entry in the collection as the hash code is likely to change. For example, in a map you wouldn't even be able to look up the value with the same object as the key, as the first test is by hash code.
StringBuffer
(and StringBuilder
) are designed to be very transient objects - create them, append to them, convert them to strings, then you're done. Any time you find yourself adding them to collections, you need to take a step back and see whether it really makes sense. Just occasionally it might do, but usually only when the collection itself is shortlived.
You should consider this in your own code when overriding equals
and hashCode
- it's very rarely a good idea for equality to be based on any mutable aspect of an object; it makes the class harder to use correctly, and can easily lead to subtle bugs which can take a long time to debug.
Did it occur to you to see the equals() method (or the lack of it) in the StringBuffer? There lies the answer for you.
A Set or for that matter any hash based collection depends on the contract exposed by the equals() and hashcode() method on the Object for their behavior characteristic.
In your case since StringBuffer doesn't override these methods each StringBuffer instance that you create is different i.e new StringBuffer("abc") == new StringBuffer("abc") will return false.
I am curious as to why would someone add StringBuffer to a set.
Most mutable object don't assume that if they happen to contain the same data they are the same. As they are mutable you can change the contents any time. i.e. it might be the same now, but not later, or it might be different now, but be the same later
BTW You shouldn't use StringBuffer if StringBuilder is an option. StringBuffer was replaced more than ten years ago.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With