I am encountering a weird behavior when trying to see if two sets are equal. I have overridden the equals and hashcode:
public class Metric {
private String id;
private Sensor sensor;
private String metricName;
private String metricDescription;
//getters, setters, toString()...
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((metricDescription == null) ? 0 : metricDescription.hashCode());
result = prime * result + ((metricName == null) ? 0 : metricName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Metric other = (Metric) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (metricDescription == null) {
if (other.metricDescription != null)
return false;
} else if (!metricDescription.equals(other.metricDescription))
return false;
if (metricName == null) {
if (other.metricName != null)
return false;
} else if (!metricName.equals(other.metricName))
return false;
return true;
}
}
I have intentionally left the Sensor information out of the hashCode and equals, but in both so it should not make a difference.
Now, consider the following code:
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(datasource);
session.save(sensorType);
session.save(sensor);
session.save(metric1);
session.save(metric2);
session.getTransaction().commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
if (session.isOpen())
session.close();
}
try {
session = sessionFactory.getCurrentSession();
tx = session.beginTransaction();
sameSensor = (Sensor) session.get(Sensor.class, new String(sensor.getId()));
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
throw e;
} finally {
if (session.isOpen())
session.close();
}
// simply retrieve the metrics
Set<Metric> sensorMetrics = sensor.getMetrics();
Set<Metric> sameSensorMetrics = sameSensor.getMetrics();
System.out.println("SENSOR METRIC");
for(Metric m : sensorMetrics) {
System.out.println(m.getMetricName() + ":" + m.hashCode());
System.out.println(sameSensorMetrics.contains(m));
}
System.out.println("SAME SENSOR METRIC");
for(Metric m : sameSensorMetrics) {
System.out.println(m.getMetricName() + ":" + m.hashCode());
System.out.println(sensorMetrics.contains(m));
}
The two sets should be identical (and all the hascodes are), but I am getting the following result:
SENSOR METRIC
metric2name_addSensor_1393695505000:-1437647480
true
metric1name_addSensor_1393695505000:2040143911
true
SAME SENSOR METRIC
metric1name_addSensor_1393695505000:2040143911
false
metric2name_addSensor_1393695505000:-1437647480
false
Even though the metrics are the same (I have checked the equals on all the pairs, the results are correct) the metrics are contained in one set but not the other... I really can't explain this and would appreciate any help.
I have given code snippets that I believe are the important ones, if any more information is needed I will be more than happy to provide. Thanks.
EDIT:
1) The code where Sensor is initialized as dfb requested:
/*
* Create all the sensor-related information to insert
*/
DataSource datasource = new DataSource();
datasource.setDatasourceName(
createUniqueString("datasource","addSensor"));
datasource.setDatasourceDescription(
createUniqueString("datasource","addSensor","description"));
SensorType sensorType = new SensorType();
sensorType.setSensorTypeName(
createUniqueString("sensortype","addSensor"));
sensorType.setSensorTypeDescription(
createUniqueString("sensortype","addSensor","description"));
Sensor sensor = new Sensor();
sensor.setDatasource(datasource);
sensor.setSensorType(sensorType);
sensor.setSensorName(createUniqueString("sensorname","addSensor"));
sensor.setSensorDescription(createUniqueString("sensordesc","addSensor","description"));
Metric metric1 = new Metric();
metric1.setMetricDescription(
createUniqueString("metric1name","addSensor","description"));
metric1.setMetricName(
createUniqueString("metric1name","addSensor"));
metric1.setSensor(sensor);
Metric metric2 = new Metric();
metric2.setMetricDescription(
createUniqueString("metric2name","addSensor","description"));
metric2.setMetricName(
createUniqueString("metric2name","addSensor"));
metric2.setSensor(sensor);
sensor.addMetric(metric1);
sensor.addMetric(metric2);
And the Sensor constructor:
Sensor() {
this.metrics = new HashSet<Metric>();
}
2) The weird behavior seems to be the Sensor instance that was saved, not the one that was loaded:
Set<Metric> sensorMetrics2 = sensor.getMetrics();
Set<Metric> sensorMetrics = sensor.getMetrics();
System.out.println(sensorMetrics2.equals(sensorMetrics));
System.out.println(sensorMetrics.equals(sensorMetrics));
Set<Metric> sameSensorMetrics2 = sameSensor.getMetrics();
Set<Metric> sameSensorMetrics = sameSensor.getMetrics();
System.out.println(sameSensorMetrics2.equals(sameSensorMetrics));
System.out.println(sameSensorMetrics.equals(sameSensorMetrics2));
The results:
false
false
true
true