I have this code written by someone else and I am having hard time to understand it.
It is working fine and generates correct result but I couldn't understand how it works
package you;
import clowns.Clown;
import clowns.Volkswagen;
public class You {
static int counter = 0;
static Volkswagen vw = new Volkswagen();
public static void main(String args[]) {
vw.add(new RecursiveClown());
vw.done();
}
static class RecursiveClown extends Clown {
public int hashCode() {
if (++counter < 20) {
vw.add(new RecursiveClown());
}
return super.hashCode();
}
}
}
couldn't understand that apparently RecursiveClown is not being called anywhere neither its hashcode() function
then how come it works and add RecursiveClown object.
also why it is returning super.hashCode();
there is this other class, that was referenced in above code.
package clowns;
import java.util.HashSet;
import java.util.Set;
public class Volkswagen {
private static final int CAPACITY = 5;
private Set<Clown> clowns = new HashSet<Clown>();
public synchronized void add(Clown clown) {
if (clowns.size() >= CAPACITY) {
throw new IllegalStateException("I'm full");
} else {
clowns.add(clown);
}
}
public synchronized void done() {
if (clowns.size() == 20) {
// The goal is to reach this line
System.out.println("I'm a Volkswagen with 20 clowns!");
}
}
}
output of these two classes are: I'm a Volkswagen with 20 clowns!
but whenever I printed
clowns.size()
in add() method of 'Volkswagen' it always return 0 then How come it compares
clowns.size() == 20
and evaluates it as true?
The explanation why your Volkswagen contains more clowns than its capacity allows is because of the way the clowns are added.
It is essentially within the line
clowns.add(clown);
in method Volkswagen.add(). It first calls hashCode of the clown to be added and then adds it to its internal structure. Since hashCode recursively calls Volkswagen.add() again, at this point the clown was not yet added to the (internal data structure backing) HashSet, thus size() returns 0.
This way the capacity is not reached at the begin of method Volkswagen.add(), but only when exiting this method (because only then clowns are actually added to the HashSet).
The Set<Clowns> is an HashSet, which is itself backed up by a HashMap.
So, basically, when you add an object to the Set<Clowns>, it will invoke HashMap.put().
HashMap.put() call the hashCode() method of the provided object.
That's why your object's hashCode() method is invoked without explicit call.
The function HashSet.add will, as fge mentioned, check the hashcode of the object, before it is added, which means that before clown #1 is added, the Volkswagan.add function for clown #2 is called.
This follows until there is a 20 deep recursion in the hashcode function, and once that terminates all 20 clowns are added at one go.
The code relies on HashSet relying itself on .hashCode().
When an element is inserted into a HashSet, this implementation of Set determines the uniqueness of the element by first calling .hashCode() on the element to add; if and only if the hash code equals another one is .equals() considered.
It returns super.hashCode() because this is Object's one: Clown does not override it.
Since RecursiveClown extends Clown, it is possible to add it to a Set of Clowns. When adding one, .hashCode() adds another recursive clown to the Volkswagen, until counter reaches 20.
Related
I read About System.identityHashCode(Object x). You can not override it because its static method but i can override Object's hashCode method. and also this is mentioned for System.identityHashCode(Object x) in javadoc as :
Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides
hashCode().The hash code for the null reference is zero.
but when i am running below code by swapping the object in println method i am getting same result.
public class SherlockGCD {
public int hashCode()
{
return super.hashCode();
}
public static void main(String[] args) {
SherlockGCD sher= new SherlockGCD();
SherlockGCD sher1= new SherlockGCD();
System.out.println(System.identityHashCode(sher));
System.out.println(sher1.hashCode());
}
}
Output is :
31866429
16795905
but if you swap the object as below then also same output
System.out.println(System.identityHashCode(sher1));
System.out.println(sher.hashCode());
Output is :
31866429
16795905
so why output is not reversing as i am changing the object in println method??
but when i am running below code by swapping the object in println method i am getting same result.
You shouldn't compare the results of a hashCode in one run with the results in a different run. For example, what you may have observed is that identity hash codes are allocated lazily - so whichever object you request the hash code for first gets 31866429 and the next gets 16795905 - on your particular system.
If you reverse the order within a single run you should see consistent results:
System.out.println(System.identityHashCode(sher));
System.out.println(sher1.hashCode());
System.out.println(System.identityHashCode(sher1));
System.out.println(sher.hashCode());
Here lines 1 and 4 of the output should have the same value, and lines 2 and 3 should have the same value.
It's unclear what you are trying to do. A given object reference has a given hashCode. This will be returned for both identityHashCode and a non-overridden hashCode. You however have two different object references. Therefore these will have different hashCodes if Object.hashCode is not overriden.
That you are seeing the same hashCodes between runs is chance. If you do this for long enough, and across enough JVM reboots that won't be the case.
The fact that you do see the same hashCodes in the same order is because the hashCodes are being allocated to the object reference only when you first call hashCode, not when the object is created. Therefore the first call to hashCode gets the first code in both runs, regardless of which object it is.
Try
// both lines output the same hashCode for sher
System.out.println(System.identityHashCode(sher));
System.out.println(sher.hashCode());
and
// both lines output the same hashCode for sher1
System.out.println(System.identityHashCode(sher1));
System.out.println(sher1.hashCode());
If you put all 4 lines next to each other you will see two identical lines, and then two more identical lines different to the first pair.
If you now want to return a different hashCode for hashCode() and identityHashCode then add a field and return a hashCode inside your override:
public class SherlockGCD {
private int id;
public SherlockGD(int id) { this.id = id; }
public int hashCode()
{
return id;
}
...
I am using a Tree Set to store some Signals as objects in my Tree Set and also want to update an object If the same signal comes again. So far I tried something but the problem is I am not able to get the complete object when I try to print it and Secondly I don't know if there is any way to update an abject and save it back to the set...
Here is my code
Signal Class (Signal.java)
public class Signal implements Comparable<Signal>{
String source;
String name;
int occurance;
public void setSource(String source){
this.source = source;
}
public void setName(String name){
this.name = name;
}
public void setOccurance(int occurance){
this.occurance = occurance;
}
public String getSource(){
return this.source;
}
public String getName(){
return this.name;
}
public int getOccurnace(){
return this.occurance;
}
#Override
public int compareTo(Signal arg0) {
// TODO Auto-generated method stub
return 0;
}
}
My Main Class
public class SortedSetTest {
public static void main(String[] args) {
// Create the sorted set
SortedSet<Signal> set = new TreeSet<Signal>();
//Create a Signal object for each new signal
Signal sig = new Signal();
sig.setSource("Source");
sig.setName("Signal Name");
sig.setOccurance(1);
// Add elements to the set
set.add(sig);
System.out.println(set);
The above print show me as object...How Can I see the set as String?
// Iterating over the elements in the set
Iterator<Signal> it = set.iterator();
while (it.hasNext()){
Here I want to print each object
For example take the first object and print the object (Signal) Source, Name and occurance and so on till the end of the set reaches.
}
}
}
The lines you're looking for:
while (it.hasNext()){
Signal sig = (Signal)it.next();
System.out.println(sig.getName());
System.out.println(sig.getOccurance());
// do the same with source or whatever property
}
You need to override toString in your Signal object to obtain a string that is more user-friendly than the default implementation in the Object class.
Also note that because all your Signals are equal based on your implementation of compareTo (always return 0) you won't be able to add more than one Signal to your set.
You are correctly printing the set.
You just haven't implemented the Signal.toString() method to represent a Signal object the way you want it.
About updating objects in a TreeSet: the object must not be modified in such a way that the output of compareTo is changed. If it needs to be updated in this way, remove it (using Set.remove(object), update it and add it back.
That said, your compareTo() method always returns 0. It should return arg0.occurence - occurence if you want higher occurence values to come before lower ones.
This is because returning a value less than 0 means this comes before the argument. 0 means equal ordering and > 1 means this comes after the argument.
Also, if you implement compareTo() you define the natural ordering of the class. It is strongly recommended to also override equals() and return true if and only if compareTo() returns 0. See http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html (search for 'consistent with equals'). With the above implementation of compareTo(), this would mean returning true only when they both have the same occurence value. If you don't want to implement equals this way (it is probably not correct) then you should write a class that implements Comparator<Signal> and pass that to the TreeSet constructor.
First of all you need to override toString method,insteadof using mutator methods try to use a constructor which implements all your instance variables and the third thing is TreeSet uses a
Red-Black tree structure,and guarantees that the elements will be ascending order,according to the natural order.So in compareTo() method you can compare one of your variables to get the solution.
If I do the following
myObject.myMethod(myClass.getComparator());
with
public void myMethod(Comparator<? super myOtherObject> comparator) {
if (comparator.equals(myClass.getComparator()) {
//do sth
}
}
and in myClass
static Comparator<ListItem> getComparator() {
return new Comparator<myOtherObject>() {
public int compare(myOtherObjectitem1, myOtherObjectitem2) {
return (Integer.valueOf(myOtherObject.getRating()).compareTo(Integer.valueOf(myOtherObject.getRating())));
}
};
}
then "//do sth" is not gonna be executed. So the objects I get from getComparator the two times are different. How can that be? Is there a chance to see, which comparator "myMethod" gets?
You're calling the equals method on this line:
if (comparator.equals(myClass.getComparator())
Since you haven't defined this method explicitly on your Comparator class (which is an anonymous inner class), this defaults to the version inherited from Object - which considers two references equal only if they are the exact same object.
And your getComparator() method states return new Comparator() { ... }, so it's calling the constructor and creating a new object each time it's called. Thus the result of one call to getComparator will be a distinct object, and hence will not be considered equal to, the result of another call.
I can think of two possible ways to change your code so that the equality test returns true:
Create the comparator only once, and return this same object from
getComparator. This would involve a change somewhat like the
following in myClass:
private static Comparator<ListItem> cmp = new Comparator<myOtherObject>() {
public int compare(myOtherObjectitem1, myOtherObjectitem2) {
return (Integer.valueOf(myOtherObject.getRating()).compareTo(Integer.valueOf(myOtherObject.getRating())));
}
};
static Comparator<ListItem> getComparator() {
return cmp;
}
Provide an explicit equals() implementation (and thus a hashCode() one too, ideally). You can then control exactly which objects are considered equal to one of your comparators. This might be much easier if you define a concrete class for your comparator rather than it being an anonymous inner class.
At the end of the day, though, I fear your approach might not be right. What does it mean for two comparators to be equal to one another? I feel this is an ambiguous concept for anything other than data classes, and I would be hesitant to use the Object.equals method for this.
(For example, if by equality you mean "they will sort lists in the same order", then I'd add a method to your comparator class called isEquivalentSortOrder or something similar. This way you can specify exactly what you mean without having to rely on the woolly definition of "being the same".)
Why not to create inside myClass static variable of Comparator like:
class myClass{
public static Comparator<ListItem> = new Comparator<myOtherObject>() {
public int compare(myOtherObjectitem1, myOtherObjectitem2) {
...
}
};
}
I have a doubt from the book Efective Java. The doubt is regarding equals method
reflexive rule violation. The book says the following:
"If you were to violate it and then add an instance of your class to a collection, the collection's contains method would almost certainly say that the collection did not contain the instance that you just added."
To test it I wrote an example class, but the contains method doesn't return false It returns true. Can anybody tell what is the problem?
I agree that the result of this program is indeed puzzling:
import java.util.*;
class Item {
#Override
public boolean equals(Object obj) {
return false; // not even equal to itself.
}
}
class Test {
public static void main(String[] args) {
Collection<Item> items = new HashSet<Item>();
Item i = new Item();
items.add(i);
System.out.println(items.contains(i)); // Prints true!
}
}
The answer is that the contains implementation checks argument == object before doing argument.equals(object). The result from contains is true since item == item holds, even though item.equals(item) returns false.
Assuming equals follows its contract (is reflexive), this way of implementing contains is correct.
If you read the quote you posted carefully, the author includes the word "almost" :) It seems you stumbled across one of the few exceptions to the rule.
Other collections (ArrayList for instance) uses equals directly, and if you change from new HashSet<Item>() to new ArrayList<Item>() in the above program it prints false as expected.
Reflexive means x.equals(x) should return true
class Foo {
int i;
public boolean equals(Object obj) {
return ((Foo) obj).i < this.i;
}
}
this will return false. And when you put it into a list and call list.contains(foo) it will return false, because none of the elements in the list was equal to the one you passed. This is so because list.contains(..) iterates the elements and for each of them checks if (elem.equals(arg))
See the docs of Collection.contains(..)
Ok, I have heard from many places and sources that whenever I override the equals() method, I need to override the hashCode() method as well. But consider the following piece of code
package test;
public class MyCustomObject {
int intVal1;
int intVal2;
public MyCustomObject(int val1, int val2){
intVal1 = val1;
intVal2 = val2;
}
public boolean equals(Object obj){
return (((MyCustomObject)obj).intVal1 == this.intVal1) &&
(((MyCustomObject)obj).intVal2 == this.intVal2);
}
public static void main(String a[]){
MyCustomObject m1 = new MyCustomObject(3,5);
MyCustomObject m2 = new MyCustomObject(3,5);
MyCustomObject m3 = new MyCustomObject(4,5);
System.out.println(m1.equals(m2));
System.out.println(m1.equals(m3));
}
}
Here the output is true, false exactly the way I want it to be and I dont care of overriding the hashCode() method at all. This means that hashCode() overriding is an option rather being a mandatory one as everyone says.
I want a second confirmation.
It works for you because your code does not use any functionality (HashMap, HashTable) which needs the hashCode() API.
However, you don't know whether your class (presumably not written as a one-off) will be later called in a code that does indeed use its objects as hash key, in which case things will be affected.
As per the documentation for Object class:
The general contract of hashCode is:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
Because HashMap/Hashtable will lookup object by hashCode() first.
If they are not the same, hashmap will assert object are not the same and return not exists in the map.
The reason why you need to #Override neither or both, is because of the way they interrelate with the rest of the API.
You'll find that if you put m1 into a HashSet<MyCustomObject>, then it doesn't contains(m2). This is inconsistent behavior and can cause a lot of bugs and chaos.
The Java library has tons of functionalities. In order to make them work for you, you need to play by the rules, and making sure that equals and hashCode are consistent is one of the most important ones.
Most of the other comments already gave you the answer: you need to do it because there are collections (ie: HashSet, HashMap) that uses hashCode as an optimization to "index" object instances, an those optimizations expects that if: a.equals(b) ==> a.hashCode() == b.hashCode() (NOTE that the inverse doesn't hold).
But as an additional information you can do this exercise:
class Box {
private String value;
/* some boring setters and getters for value */
public int hashCode() { return value.hashCode(); }
public boolean equals(Object obj) {
if (obj != null && getClass().equals(obj.getClass()) {
return ((Box) obj).value.equals(value);
} else { return false; }
}
}
The do this:
Set<Box> s = new HashSet<Box>();
Box b = new Box();
b.setValue("hello");
s.add(b);
s.contains(b); // TRUE
b.setValue("other");
s.contains(b); // FALSE
s.iterator().next() == b // TRUE!!! b is in s but contains(b) returns false
What you learn from this example is that implementing equals or hashCode with properties that can be changed (mutable) is a really bad idea.
It is primarily important when searching for an object using its hashCode() value in a collection (i.e. HashMap, HashSet, etc.). Each object returns a different hashCode() value therefore you must override this method to consistently generate a hashCode value based on the state of the object to help the Collections algorithm locate values on the hash table.