我在尝试查看两个集合是否相等时遇到了一个奇怪的行为。我已经覆盖了 equals 和哈希码:
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;
}
}
我有意将传感器信息排除在 hashCode 和 equals 之外,但在两者中应该没有区别。
现在,考虑以下代码:
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));
}
这两个集合应该是相同的(并且所有的 hascode 都是),但我得到以下结果:
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
即使指标相同(我已经检查了所有对的相等性,结果是正确的)指标包含在一组而不是另一组中......我真的无法解释这一点并且会很感激任何帮助。
我已经给出了我认为很重要的代码片段,如果需要更多信息,我将非常乐意提供。谢谢。
编辑:
1)根据dfb请求初始化传感器的代码:
/*
* 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);
和传感器构造函数:
Sensor() {
this.metrics = new HashSet<Metric>();
}
2) 奇怪的行为似乎是保存的传感器实例,而不是加载的实例:
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));
结果:
false
false
true
true
最佳答案
以下构造对于 Hibernate 来说是有问题的,因为 Hibernate 由于需要延迟加载而倾向于为实体创建代理:
if (getClass() != obj.getClass())
return false;
Proxy 是 Metrics 的子类,这就是为什么上面的代码不起作用,但代码可能起作用:
if (!(obj instanceof Metrics)) {
return false;
}
有关覆盖实体的 equals 和 hashcode 的更多说明,请参见 Hibernate documentation . instanceof 也可以带来惊喜,如 this 中所述博文。
关于java - Set.equals 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22118114/