Win a copy of Beginning Java 17 Fundamentals: Object-Oriented Programming in Java 17 this week in the Java in General forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Ron McLeod
  • Liutauras Vilda
  • Jeanne Boyarsky
Sheriffs:
  • Junilu Lacar
  • Rob Spoor
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Tim Moores
  • Jesse Silverman
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Piet Souris
  • Frits Walraven

HashSet

 
Ranch Hand
Posts: 244
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
import java.util.*;

public class Test
{
private String s;
public Test(String s)
{
this.s = s;
}
public static void main(String args[])
{
HashSet<Object> hs = new HashSet<Object>();
hs.add(new Test("km"));
hs.add(new Test("km"));
hs.add(new String("km"));
hs.add(new String("km"));
hs.add(new StringBuffer("km"));
hs.add(new StringBuffer("km"));
System.out.print(hs.size());
}
}


Can anybody explain me why the result differs only for 'String'?
 
Bartender
Posts: 1638
IntelliJ IDE MySQL Database Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Kousik,
welcome to Javaranch.
It would have been nice if you could have given the output and what is it that you did not understand.
This link gives quite a few hints at how to ask questions on Java ranch. You can go through it at leisure!
Although this is one of the links in the above faq entry, when posting code you must put it inside the code tags (A lot of tags are available just under the editor text area while writing a post.)

Coming to your question. I think you wanted to ask as to why the size of hashset is 5 when you have put 6 objects. Isn't ?

The answer is that two strings are considered to be equal, if all the characters in the two strings are exactly equal in case and order.
For StringBuffers, the default implementation of equals is not overridden, so two references are equal if they point to the same object instance. Same with your Test class.
If i alter your code to implement equals and hashcode for Test, then the size will be 4.

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In the example after overriding the methods equals() and hashCode() which two objects become equal, i mean whether objects of Test or StringBuffer are equal, which reduces the size of the HashSet to 4. Pls. explain.
 
Vijay Krishna Doddala
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In the example after overriding the methods equals() and hashCode() which two objects become equal, i mean whether objects of Test or StringBuffer are equal, which reduces the size of the HashSet to 4. Pls. explain.
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE MySQL Database Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Vijay Krishna Doddala:
In the example after overriding the methods equals() and hashCode() which two objects become equal, i mean whether objects of Test or StringBuffer are equal, which reduces the size of the HashSet to 4. Pls. explain.


Which objects do you think will be equal when i have overriden the equals and hashcode methods of class Test?
 
Ranch Hand
Posts: 1274
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Howdy Vijay,

seems to be one of your first postings here, so:

Welcome to the Ranch!




The add() method of Set returns a boolean if the thing was really added.
So instead of a line
add(something);

perhaps use
System.out.println(add(something));


So you can see what object was added immediately.

Yours,
Bu
 
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi kousik,
String objects are maintained in the String Constant Pool.Once the String object is created, it'll maintained in the String Pool.Again the same String Object is not created, it'll be referred from the pool.In this code, you've created the same String Object two times.That second String Object is not newly created, it'll be referred from the pool and HashSet doesn't allow duplicates.So only one String Object is added in the HashSet.

Pls tell me, if i could wrong.

regards,
arthanari.
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE MySQL Database Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by geethapuni arthanari:
hi kousik,
String objects are maintained in the String Constant Pool.Once the String object is created, it'll maintained in the String Pool.Again the same String Object is not created, it'll be referred from the pool.In this code, you've created the same String Object two times.That second String Object is not newly created, it'll be referred from the pool and HashSet doesn't allow duplicates.So only one String Object is added in the HashSet.

Pls tell me, if i could wrong.

regards,
arthanari.


Well not really, only string constants are present in the constants pool i.e the compile time constants.
In case one does a new String() then its a new object that is created. In order to refer to an an instance from the constants pool you can use String.intern()
equals and override methods are overloaded for String class such that two strings are deemed to be equal if they have exactly same sequence of character in them. So, how many ever times you do a new String("xyz") the two references will be equal(i.e String1.equals(String2) will return true) but will not point to the same object.
Hope this is clear.
 
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I just ran some tests on the SUN 1.4 and 1.5 JVM to remove the speculation.

The key here is calling the constructor of String - there's really NO reason to use it, and it is looked at as amateur in the organizations I've worked with.

Strings are immutable, so it doesn't matter what reference you're using.

The difference here is non-compile time constants also exist in the String pool - for example:

public static void main(String[] args) {

String aString = "test";
String bString = "test";
System.out.println(aString == bString);
}

returns true

To conserve memory, you should only use the new String("String") constructor when you want a unique object in memory (and this is very very very rare). Saying new String("String") is like saying new Object(new Object)).

This is a little strange, too, because if a String is dynamically created (ie. a method call) it will create a new object in memory too:

public static void main(String[] args) {

String aString = "test";
String bString = "test";
String cString = st() + te();
String dString = "te" + "st";
String eString = "te" + st();
System.out.println(aString == bString);
System.out.println(aString == cString);
System.out.println(aString == dString);
System.out.println(aString == eString);

}

private static String st() {
return "st";
}

private static String te(){
return "te";
}


Output is:

true
false
true
false


If a portion of a string is created from a method call, it be a newly created String object.
[ October 04, 2007: Message edited by: Adam Schaible ]
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE MySQL Database Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Adam Schaible:
The key here is calling the constructor of String - there's really NO reason to use it, and it is looked at as amateur in the organizations I've worked with.


Bang on! The organizations you have worked with have the rite ideas

Originally posted by Adam Schaible:

The difference here is non-compile time constants also exist in the String pool - for example:

public static void main(String[] args) {

String aString = "test";
String bString = "test";
System.out.println(aString == bString);
}

returns true



Well the two strings above are compile time constants. These will exist in the constants pool. A compile time constant is something whose value can be determined at compile time. This is the reason why if you create a part of the string from a method call, it does not add to the constants pool. The reason being a method call is bound at runtime.(of course if it is not final)
[ October 04, 2007: Message edited by: Nitesh Kant ]
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
By that logic, wouldn't the new String("test") also be a compile time constant?

The String class is final, so why would it's value not be known at compile time? The JLS is somewhat vague on this:

A new class instance is explicitly created when evaluation of a class instance creation
expression (�15.9) causes a class to be instantiated.
A new class instance may be implicitly created in the following situations:
� Loading of a class or interface that contains a String literal (�3.10.5) may
create a new String object to represent that literal. (This might not occur if
the same String has previously been interned (�3.10.5).)
� Execution of an operation that causes boxing conversion (�5.1.7). Boxing
conversion may create a new object of a wrapper class associated with one of
the primitive types.
� Execution of a string concatenation operator (�15.18.1) that is not part of a
constant expression sometimes creates a new String object to represent the
result. String concatenation operators may also create temporary wrapper
objects for a value of a primitive type.

Anyone have a better reference?


***UPDATE***

I take that back, it's not unclear:

Each string literal is a reference (�4.3) to an instance (�4.3.1, �12.5) of class
String (�4.3.3). String objects have a constant value. String literals�or, more generally, strings that are the values of constant expressions (�15.28)�are �interned� so as to share unique instances, using the method String.intern.

15.28 Constant Expression

A compile-time constant expression is an expression denoting a value of
primitive type or a String that does not complete abruptly and is composed
using only the following:
� Literals of primitive type and literals of type String (�3.10.5)
� Casts to primitive types and casts to type String
� The unary operators +, -, ~, and ! (but not ++ or --)
� The multiplicative operators *, /, and %
� The additive operators + and -
� The shift operators <<, >>, and >>>
� The relational operators <, <=, >, and >= (but not instanceof)
� The equality operators == and !=
� The bitwise and logical operators &, ^, and |
� The conditional-and operator && and the conditional-or operator ||
� The ternary conditional operator ? :
� Parenthesized expressions whose contained expression is a constant expression.
� Simple names that refer to constant variables (�4.12.4).
� Qualified names of the form TypeName . Identifier that refer to constant variables
(�4.12.4).
Compile-time constant expressions are used in case labels in switch statements
(�14.11) and have a special significance for assignment conversion (�5.2).

Compile- time constants of type String are always �interned� so as to share unique instances, using the method String.intern.
A compile-time constant expression is always treated as FP-strict (�15.4),
even if it occurs in a context where a non-constant expression would not be considered
to be FP-strict.
Examples of constant expressions:
true
(short)(1*2*3*4*5*6)
Integer.MAX_VALUE / 2
2.0 * Math.PI
"The integer " + Long.MAX_VALUE + " is mighty big."
[ October 04, 2007: Message edited by: Adam Schaible ]
reply
    Bookmark Topic Watch Topic
  • New Topic