У меня конфликт с использованием Apache Commons Lang HashCodeBuilder с использованием версии 3.4. Я хеширую объект Route, который содержит два объекта Cell, начало и конец. В конце я привожу пример столкновения. Оба класса переопределяют методы hashCode и equals. Сначала класс Cell:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Cell {
private int east;
private int south;
public Cell(int east, int south) {
this.east = east;
this.south = south;
}
public int getEast() {
return east;
}
public void setEast(int east) {
this.east = east;
}
public int getSouth() {
return south;
}
public void setSouth(int south) {
this.south = south;
}
@Override
/**
* Compute hash code by using Apache Commons Lang HashCodeBuilder.
*/
public int hashCode() {
return new HashCodeBuilder(17, 31)
.append(this.south)
.append(this.east)
.toHashCode();
}
@Override
/**
* Compute equals by using Apache Commons Lang EqualsBuilder.
*/
public boolean equals(Object obj) {
if (!(obj instanceof Cell))
return false;
if (obj == this)
return true;
Cell cell = (Cell) obj;
return new EqualsBuilder()
.append(this.south, cell.south)
.append(this.east, cell.east)
.isEquals();
}
}
И класс Route:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import java.util.*;
public class Route {
private Cell startCell;
private Cell endCell;
public Route(Cell startCell, Cell endCell) {
this.startCell = startCell;
this.endCell = endCell;
}
public Cell getStartCell() {
return startCell;
}
public void setStartCell(Cell startCell) {
this.startCell = startCell;
}
public Cell getEndCell() {
return endCell;
}
public void setEndCell(Cell endCell) {
this.endCell = endCell;
}
@Override
public int hashCode() {
return new HashCodeBuilder(43, 59)
.append(this.startCell)
.append(this.endCell)
.toHashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Route))
return false;
if (obj == this)
return true;
Route route = (Route) obj;
return new EqualsBuilder()
.append(this.startCell, route.startCell)
.append(this.endCell, route.endCell)
.isEquals();
}
}
Пример столкновения:
public class Collision {
public static void main(String[] args) {
Route route1 = new Route(new Cell(154, 156), new Cell(154, 156));
Route route2 = new Route(new Cell(153, 156), new Cell(151, 158));
System.out.println(route1.hashCode() + " " + route2.hashCode());
}
}
Вывод: 1429303 1429303. Теперь, если я изменю начальное нечетное число и нечетное число множителя одинаковыми для обоих классов, то этот пример не будет конфликтовать. Но в документации для HashCodeBuilder четко указано:
Необходимо передать два случайно выбранных нечетных числа. В идеале эти должны быть разными для каждого класса, однако это не важно.
В идеале я хотел бы иметь идеальную хеш-функцию (инъективная функция) для моего примера, если это вообще возможно.