Porównanie dwóch tablic bajtowych? (Jawa)

96

Mam tablicę bajtów z ~ znaną sekwencją binarną. Muszę potwierdzić, że sekwencja binarna jest taka, jaka powinna być. Próbowałem .equalsdodatkowo ==, ale żaden z nich nie działał.

byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
if (new BigInteger("1111000011110001", 2).toByteArray() == array){
    System.out.println("the same");
} else {
    System.out.println("different'");
}
zrozumiałem
źródło
czy możesz bezpośrednio porównać struny?
obiekty
1
@obiekty - zera wiodące. Poza tym, rzeczy String / BigInteger mogą być po prostu sposobem zilustrowania pytania dotyczącego porównania tablicy bajtów.
Stephen C
Czy próbowałeś użyć metody compareTo? BTW ==porównuje prymitywne wartości po prostu
fyi
Oto powiązane pytanie dotyczące częściowego porównania tablicy: stackoverflow.com/questions/16646967/ ...
Vadzim

Odpowiedzi:

167

W swoim przykładzie masz:

if (new BigInteger("1111000011110001", 2).toByteArray() == array)

W przypadku obiektów ==w java porównuje wartości referencyjne . Sprawdzasz, czy odwołanie do tablicy zwróconej przez toByteArray()jest takie samo jak odwołanie w niej zawarte array, co oczywiście nigdy nie może być prawdą. Ponadto klasy tablicowe nie przesłaniają, .equals()więc zachowanie jest takie, w Object.equals()którym porównuje się tylko wartości referencyjne.

Aby porównać zawartość dwóch tablic, klasa Arrays udostępnia statyczne metody porównywania tablic

byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
byte[] secondArray = new BigInteger("1111000011110001", 2).toByteArray();
if (Arrays.equals(array, secondArray))
{
    System.out.println("Yup, they're the same!");
}
Brian Roach
źródło
64

Sprawdź statyczną java.util.Arrays.equals()rodzinę metod. Jest taki, który robi dokładnie to, czego chcesz.

Ernest Friedman-Hill
źródło
11

Java nie przeciąża operatorów, więc zazwyczaj będziesz potrzebować metody dla typów innych niż podstawowe. Wypróbuj metodę Arrays.equals () .

jswolf19
źródło
11

Możesz użyć obu Arrays.equals()i MessageDigest.isEqual(). Te dwie metody mają jednak pewne różnice.

MessageDigest.isEqual()jest metodą porównywania opartą na stałej czasowej i Arrays.equals()nie jest stała w czasie i może powodować pewne problemy z bezpieczeństwem, jeśli jest używana w aplikacji zabezpieczającej.

Szczegóły różnicy można znaleźć pod adresem Arrays.equals () vs MessageDigest.isEqual ()

PixelsTech
źródło
3

Oczywiście zaakceptowana odpowiedź Arrays.equal (najpierw bajt [], sekunda bajt []) jest poprawna. Lubię pracować na niższym poziomie, ale nie mogłem znaleźć wydajnej funkcji niskiego poziomu do wykonywania zakresów testu równości. Musiałem sam sobie ubić, gdyby ktoś tego potrzebował:

public static boolean ArraysAreEquals(
 byte[] first,
 int firstOffset,
 int firstLength,
 byte[] second,
 int secondOffset,
 int secondLength
) {
    if( firstLength != secondLength ) {
        return false;
    }

    for( int index = 0; index < firstLength; ++index ) {
        if( first[firstOffset+index] != second[secondOffset+index]) {
            return false;
        }
    }

    return true;
}
Bamaco
źródło
Jest to dobre rozwiązanie do testowania raczej podzbioru tablic niż całości. Należy jednak zauważyć, że Arrays.equals (byte [], byte []) robi prawie dokładnie wszystko, co tutaj zrobiłeś (z wyjątkiem bardziej wydajnej obsługi dwóch wartości będących tym samym obiektem i obsługi tablic o wartości null z wdziękiem). Mając możliwość wyboru standardowej implementacji biblioteki, która będzie wspierana przez społeczność lub piszę jej niestandardową implementację, którą będę musiał wspierać na zawsze, za każdym razem wybiorę tę pierwszą.
Tom Dibble
4
Odpowiedź jest przydatna w przypadku użycia, w którym mamy dwie tablice i chcemy porównać zakres bajtów z nich, bez uprzedniego wykonywania kopii tablic. Kopie tablicowe dodają narzut, dodają śmieci i nie są potrzebne. Potrzebowałem niskopoziomowego memcmp () w stylu c i to pasuje do potrzeb. Oczywiście memcmp () przyjmuje tylko 1 argument długości. Ta funkcja jest wystarczająco blisko.
Bamaco
2

Ponieważ chciałem porównać dwie tablice dla testu jednostkowego i doszedłem do tej odpowiedzi, pomyślałem, że mogę się podzielić.

Możesz to również zrobić za pomocą:

@Test
public void testTwoArrays() {
  byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
  byte[] secondArray = new BigInteger("1111000011110001", 2).toByteArray();

  Assert.assertArrayEquals(array, secondArray);
}

Więcej informacji można znaleźć w sekcji Porównywanie tablic w asercjach JUnit .

Sylhare
źródło