문제

바이트 배열을 맵 키로 사용하는 데 문제가 있습니까? 나는 또한 할 수 있습니다 new String(byte[]) 그리고 해시 String 그러나 사용하는 것이 더 간단합니다 byte[].

도움이 되었습니까?

해결책

문제는 그 것입니다 byte[] 객체 아이덴티티를 사용합니다 equals 그리고 hashCode, 하도록 하다

byte[] b1 = {1, 2, 3}
byte[] b2 = {1, 2, 3}

a에서 일치하지 않습니다 HashMap. 세 가지 옵션이 있습니다.

  1. a String, 그러나 문제를 인코딩해야합니다 (바이트 -> 문자열 -> 바이트가 동일한 바이트를 제공하는지 확인해야합니다).
  2. 사용 List<Byte> (메모리에서 비쌀 수 있습니다).
  3. 자신의 포장 수업을 작성하십시오 hashCode 그리고 equals 바이트 배열의 내용을 사용합니다.

다른 팁

키에 대한 참조 평등 만 원한다면 괜찮습니다. 배열은 원하는 방식으로 "가치 평등"을 구현하지 않습니다. 예를 들어:

byte[] array1 = new byte[1];
byte[] array2 = new byte[1];

System.out.println(array1.equals(array2));
System.out.println(array1.hashCode());
System.out.println(array2.hashCode());

다음과 같은 것을 인쇄합니다.

false
1671711
11394033

(실제 숫자는 관련이 없습니다. 그들이 다르다는 사실은 중요합니다.)

당신을 가정합니다 실제로 평등을 원한다면, 나는 당신이 byte[] 평등과 해시 코드 생성을 적절하게 구현합니다.

public final class ByteArrayWrapper
{
    private final byte[] data;

    public ByteArrayWrapper(byte[] data)
    {
        if (data == null)
        {
            throw new NullPointerException();
        }
        this.data = data;
    }

    @Override
    public boolean equals(Object other)
    {
        if (!(other instanceof ByteArrayWrapper))
        {
            return false;
        }
        return Arrays.equals(data, ((ByteArrayWrapper)other).data);
    }

    @Override
    public int hashCode()
    {
        return Arrays.hashCode(data);
    }
}

사용 후 바이트 배열 내에서 값을 변경하면 ByteArrayWrapper, a HashMap (etc) 키를 다시 찾는 데 문제가 있습니다 ... 데이터 사본을 ByteArrayWrapper 원한다면 생성자이지만 분명히 당신을 알고 있다면 성능 낭비가 될 것입니다. 습관 바이트 배열의 내용을 변경하십시오.

편집 : 주석에 언급 된 바와 같이, 당신은 또한 사용할 수 있습니다. ByteBuffer 이것을 위해 (특히, 그것 ByteBuffer#wrap(byte[]) 방법). 나는 그것이 정말로 옳은지, 모든 추가 능력을 감안할 때 ByteBufferS는 필요하지 않지만 옵션입니다.

우리는 이것에 바이트 버퍼를 사용할 수 있습니다 (이것은 기본적으로 비교기가있는 바이트 [] 래퍼입니다)

HashMap<ByteBuffer, byte[]> kvs = new HashMap<ByteBuffer, byte[]>();
byte[] k1 = new byte[]{1,2 ,3};
byte[] k2 = new byte[]{1,2 ,3};
byte[] val = new byte[]{12,23,43,4};

kvs.put(ByteBuffer.wrap(k1), val);
System.out.println(kvs.containsKey(ByteBuffer.wrap(k2)));

인쇄 할 것입니다

true

당신은 사용할 수 있습니다 java.math.BigInteger. 그것은 있습니다 BigInteger(byte[] val) 건설자. 참조 유형이므로 해시 가능의 키로 사용할 수 있습니다. 그리고 .equals() 그리고 .hashCode() 각각의 정수 번호에 대해 정의되며, 이는 BigInteger가 일관된 동등한 의미를 바이트 [] 배열을 가지고 있음을 의미합니다.

답이 가장 간단한 대안을 지적하지 않는다는 것에 매우 놀랐습니다.

예, 해시 맵을 사용할 수는 없지만 아무도 SortedMap을 대안으로 사용하지 못하게합니다. 유일한 것은 배열을 비교 해야하는 비교기를 작성하는 것입니다. 그것은 해시 맵만큼 성능이 없지만 간단한 대안을 원한다면 여기로 이동합니다 (구현을 숨기려면 SortedEdMap을 MAP로 바꿀 수 있습니다).

 private SortedMap<int[], String>  testMap = new TreeMap<>(new ArrayComparator());

 private class ArrayComparator implements Comparator<int[]> {
    @Override
    public int compare(int[] o1, int[] o2) {
      int result = 0;
      int maxLength = Math.max(o1.length, o2.length);
      for (int index = 0; index < maxLength; index++) {
        int o1Value = index < o1.length ? o1[index] : 0;
        int o2Value = index < o2.length ? o2[index] : 0;
        int cmp     = Integer.compare(o1Value, o2Value);
        if (cmp != 0) {
          result = cmp;
          break;
        }
      }
      return result;
    }
  }

이 구현은 다른 배열에 대해 조정될 수 있습니다. 알아야 할 유일한 것은 동일한 배열 (= 동일 회원의 동일 길이)이 0을 반환해야하며 결정적인 순서가 있다는 것입니다.

자바의 배열이 반드시 구현되는 것은 아니라고 생각합니다. hashCode() 그리고 equals(Object) 직관적으로 방법. 즉, 두 개의 동일한 바이트 배열이 반드시 동일한 해시 코드를 공유 할 필요는 없으며 반드시 동일하다고 주장하는 것은 아닙니다. 이 두 가지 특성이 없으면 해시 맵은 예기치 않게 행동합니다.

따라서 권장합니다 에 맞서 사용 byte[] 해시 맵의 키로.

BytearRkey 및 Overload Hashcode 및 동일한 방법과 같은 클래스를 만들고 동일한 방법을 사용해야합니다.

이렇게하면 바이트 배열 끝에 추가 된 0 항목을 건너 뛸 수 있으므로 더 큰 유연성을 제공합니다.

이렇게하면 두 객체가 어떻게 동일 해야하는지 결정할 것입니다.

기본 배열 구현 대신 array.equals 및 array.hashcode를 사용해야하므로 문제가 있습니다.

Arrays.tostring (바이트)

바이트 []를 Base32 또는 Base64를 사용하여 '안전한'문자열로 변환 할 수도 있습니다.

byte[] keyValue = new byte[] {…};
String key = javax.xml.bind.DatatypeConverter.printBase64Binary(keyValue);

물론 위의 변형은 다음과 같습니다.

String key = org.apache.commons.codec.binary.Base64.encodeBase64(keyValue);

다음은 Treemap, 비교기 인터페이스 및 java 메소드 java.util.arrays.equals (byte [], byte [])를 사용한 솔루션입니다.

참고 :지도의 순서는이 방법과 관련이 없습니다.

SortedMap<byte[], String> testMap = new TreeMap<>(new ArrayComparator());

static class ArrayComparator implements Comparator<byte[]> {
    @Override
    public int compare(byte[] byteArray1, byte[] byteArray2) {

        int result = 0;

        boolean areEquals = Arrays.equals(byteArray1, byteArray2);

        if (!areEquals) {
            result = -1;
        }

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