자바:객체의 고유한 속성을 얻습니다(해시코드와 같지만 충돌 방지).

StackOverflow https://stackoverflow.com/questions/1843565

  •  12-09-2019
  •  | 
  •  

문제

세트의 모든 개체에 대해 고유한 값을 생성해야 하는 작업이 있습니다.해시코드 계약에서 충돌이 허용되지 않는다면 해시코드를 사용하는 것이 완벽할 것입니다.

한 가지 아이디어:모든 개체의 해시코드를 다중 집합에 기록합니다.그런 다음 해시코드를 고유 식별자로 사용하되 해당 해시코드가 세트에 두 번 이상 있는 경우 세트에도 없는 다른 값을 사용하십시오.그러나 이것은 부피가 크고 어색한 느낌이 듭니다.

더 나은 아이디어가 있나요?

내가 이미 가지고 있는 것은 다음과 같습니다.

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)으로 개체를 보내고이를 키로 사용하십시오. 해시 값이 다른 해시를 수행 할 때 씨앗을 사용하고 해시와 관련된 물체와 관련된 씨앗을 사용해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top