views:

157

answers:

8
public class abc1 {

 private String s;

 public abc1(String s){this.s=s;}
 public static void main(String args[])
 {
  HashSet<Object> hs=new HashSet<Object>();
  abc1 a1= new abc1("abc");
  abc1 a2= new abc1("abc");
  String s1= new String("abc");
  String s2= new String("abc");
  hs.add(a1);
  hs.add(a2);
  hs.add(s1);
  hs.add(s2);
  System.out.println(hs.size());

 }
}

Why above program output is 3?

Edit

Seeing below comments I am extending my question:

System.out.println (s1 == s2);

Are s1 and s2 refering to same object? If then the above statement should print true but its output is false.

Are they are similar in terms of hashcode but still differnt?

+10  A: 

There are two unequal instances of abc1 (note that it doesn't override equals or hashCode) and one string in the set. Let's look at the four add calls:

hs.add(a1);

Originally the set is empty - so obviously this will add the value.

hs.add(a2);

This will also add the value to the set, because they are distinct objects and the default implementation of equals/hashCode is basically reference identity.

hs.add(s1);

This will add the value to the set as the string isn't equal to either of the current values (which aren't strings).

hs.add(s2);

This will not add anything to the set, as the second string is equal to the first. (String overrides equals/hashCode.)

The result is a set with three items in.

Jon Skeet
@Bill: I believe that s1 != s2 and so they are not the same instance. The reason only one is added is because HashSet uses equals, which String overrides but abc does not.
Justin Ardini
A: 

Because you're adding three unique objects -- the two abc1 objects (you would have to implement the equals and hashCode methods to define equality) and a String (only one is added because it HAS implemented these methods, and the data being compared in the String objects is equal).

Chris Dennett
+1  A: 

Here is the problem:

String s1= new String("abc");
String s2= new String("abc");

You can try to do:

System.out.println (s1 == s2);

and you see true. Set cannot contain same objects that's why only s2 is stored there.

Roman
Even after the correct there's still a problem - only a1, a2 and s1 are stored. Also, your output code will still print out false, because == checks for reference equality, not object equality.
Jon Skeet
@Jon Skeet: that was a typo as well)) I just copied the wrong block of code and then used its variable's names.
Roman
Jonathon
A: 

HashSet implements the Set interface:

public interface Set<E> extends Collection<E>

From http://java.sun.com/j2se/1.5.0/docs/api/java/util/Set.html:

A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.

Answer:

I believe s1 and s2 will be found to be equal and both can not be contained within the Set. There is no way to determine that the abc1 objects are "equal". Thus, both get added.

Tibrim
A: 

The short answer: because a HashSet is like a mathematical set, which by definition only holds distinct (unique) objects. And as others have said here, two of the objects you put in are evidently not evaluated to be distinct from each other.

John B.
A: 

Set interface does not allow duplicate elements.Thats the reason you are getting 3 as output.

String s1= new String("abc");
  String s2= new String("abc");

Even though above creates two objects but are identical elements.

giri
+2  A: 

Because the set structure (notice how your hashmap is backed by a set) does not allows two equal objects to be stored. That's how sets behave.

Now, You may be fooled to think that both a1 and a2 are equal, but if they don't override equals or hashCode then for Java they are not equal. However with your strings s1 and s2, they are indeed equal because the String implementation already overrides the equals and hashCode methods. Try doing s1.equals(s2) and you'll get a true as result. If you do a1.equals(a2) you'll get false.

At the end, your hashset contains a1, a2 and s1.

You extended your question, so to answer that...

s1 and s2 are not referring to the same object, they are two different String objects but both represent the same set of characters. Since they are not the same object, System.out.println(s1 == s2) prints false. They are equal(), but not the same object.

Cesar
A: 

Given

  abc1 a1= new abc1("abc");
  abc1 a2= new abc1("abc");

a1 != a2 as you did not provide an overridden equals() that will state that a1 and a2 is same if the string they contain is same.

..And..

HashSet will hold only unique objects.

ring bearer