자바:객체의 고유한 속성을 얻습니다(해시코드와 같지만 충돌 방지).
문제
세트의 모든 개체에 대해 고유한 값을 생성해야 하는 작업이 있습니다.해시코드 계약에서 충돌이 허용되지 않는다면 해시코드를 사용하는 것이 완벽할 것입니다.
한 가지 아이디어:모든 개체의 해시코드를 다중 집합에 기록합니다.그런 다음 해시코드를 고유 식별자로 사용하되 해당 해시코드가 세트에 두 번 이상 있는 경우 세트에도 없는 다른 값을 사용하십시오.그러나 이것은 부피가 크고 어색한 느낌이 듭니다.
더 나은 아이디어가 있나요?
내가 이미 가지고 있는 것은 다음과 같습니다.
public static <V> void toGraphViz(final Graph<V, DefaultWeightedEdge> g, String filename) {
// to avoid hashcode collisions
final Set<Integer> hashcodes = new HashSet<Integer>(g.vertexSet().size());
DOTExporter<V, DefaultWeightedEdge> dot = new DOTExporter<V, DefaultWeightedEdge>(new VertexNameProvider<V> () {
// vertex name must be unqiue
@Override
public String getVertexName(V arg0) {
int hash = arg0.hashCode();
while (hashcodes.contains((hash))) {
hash += 1;
}
return "" + hash;
}
}
편집하다: 원래는 명확하지 않았지만 ID 번호는 어떻게든 객체의 함수여야 합니다. getVertexName(V)
여러 번 호출되며 동일한 값에 대해 V
, 동일한 결과를 얻을 것입니다.
또한 Vertex 유형은 일반적입니다.따라서 이 문제를 해결하기 위해 특정 클래스를 수정할 수는 없습니다.
해결책
이 고유번호의 수명은 얼마입니까?단지 프로그램의 수명?어떤 경우에 적절한 동기화를 통해 액세스되는 클래스의 단순한 정적 카운터가 아닌 이유는 무엇입니까?각각의 새로운 객체에 대해 이를 증가시킵니다.사용한 값 목록을 유지할 필요가 없으며 사용한 가장 높은 값만 보관하면 됩니다.
많은 실행(및 아마도 많은 동시 인스턴스)에서 고유한 경우 고유한 레코드 ID를 생성하는 데이터베이스를 사용할 수 있습니다.
설명에 따라 편집됨
이전에 내가 놓친 부분은 고유한 "해시"를 생성하려는 클래스를 수정할 수 없다는 것입니다.
충돌이 일어날 클래스의 해시 코드를 가지고 작업하는 것이 삶을 힘들게 한다고 생각합니다.문제의 Vertex 클래스가 equals()를 올바르게 구현했다고 가정하면 객체 자체를 우리가 사용한 해시코드 세트의 키로 사용할 수 있습니다.
public class Hasher {
public <V> void toGraphViz(final Graph<V, DefaultWeightedEdge> g, String filename) {
final Map<V, Integer> hashcodes = new HashMap< V, Integer>();
final int latestHashHolder[] = { 0 }; // array to allow access from inner class
DOTExporter<V, DefaultWeightedEdge> dot
= new DOTExporter<V, DefaultWeightedEdge>(new VertexNameProvider<V> ()) {
// vertex name must be unqiue
@Override
public synchronized String getVertexName(V vertex) {
int hashcode;
if ( hashcodes.containsKey(vertex)){
hashcode = hashcodes.get(vertex);
} else {
hashcode = latestHashHolder[0];
latestHashHolder[0]++;
hashcodes.put(vertex, (Integer)latestHashHolder[0]);
}
return "Vertex-" + hashcode;
}
};
}
}
다른 팁
당신은 a를 사용하는 것을 고려할 수 있습니다 uuid, 당신이 성취하려는 것에 따라 ...
객체의 고유 한 값을 찾으려면 객체를 독특하게 만드는 속성의 조합을 알아야합니다.
".contains ()"을 실행하려면 ".quals ()"를 결정하는 방법이 필요합니다. 즉, 정점을 고유하게 식별하는 방법을 이미 알고 있어야하므로 고유 한 속성의 표현을 생각해 낼 수 있습니다. ?
예 : "(X, Y, Z, RGB)"
질문을 오해하지 않는 한,이 목적을 위해 객체의 해시 코드로 멍청이를 추천하지 않을 것입니다.
일련 번호 만 사용하지 않는 이유는 무엇입니까?
static private int serial=0;
static public synchronized nextSerialNumber() { return ++serial; }
또는 조합/하이브리드는 ((Hash << 32) | getNextSerial ())이라고합니다.
편집 설명을 다루기 위해
객체를 구성 할 때 일련 번호를 개인 멤버 변수에 할당하고 HashCode ()에 대해 반환하십시오. 그런 다음 super.equals ()로 호출 된 호출과 동등한 것을 재정의해야합니다 (생성 된 일련 번호는 default equals () 구현과 일치하기 때문에 해당 equals () 재정의를 보는 것이 코드를 빨간 플래그하지 않기 때문에 hashcode () 재정의가 있기 때문입니다. 도구 (및 기타 프로그래머)에게.
public class Vertex
{
private final int serial; // instance serial number
public Vertex() {
serial=nextSerialNumber();
...
}
public int hashCode() {
return serial;
}
public boolean equals(Object obj) {
return super.equals(obj); // serial number hash-code consistent with default equals
}
...
static private int nextSerial=0;
static public synchronized nextSerialNumber() { return nextSerial++; }
}
해시 코드를 오해했다고 생각합니다. 계약에 따라 Hascode는 동일 할 때 (..)가 참일 때 동일해야하며 그 반대도 마찬가지입니다. 따라서 귀하의 경우 동일한 속성을 가진 정점 만 동일한 Hascode를 가져야합니다. 그렇지 않으면 자체 서면 Hascode 계산 방법을 수정해야합니다. 내가 당신의 질문을 이해 한 한 그 자체로 정점이 독특하기 때문에 문제가 없어야합니까?
아마도 당신이하는 일을 이해하지 못하지만 각 객체에 대한 참조를 만드는 것을 고려하십시오. 참조에는 객체의 주소가 포함되어 있으므로 각 객체마다 고유합니다.
그렇게 어렵지 않습니까? Java에있는 것이 충돌을 보장하지 않으면 다른 해시 알고리즘을 사용하십시오. 해시 알고리즘 (예 : SHA-256)으로 개체를 보내고이를 키로 사용하십시오. 해시 값이 다른 해시를 수행 할 때 씨앗을 사용하고 해시와 관련된 물체와 관련된 씨앗을 사용해야합니다.