เปรียบเทียบไบต์สองอาร์เรย์? (Java)


96

ฉันมีอาร์เรย์ไบต์ที่มี ~ ลำดับไบนารีที่รู้จักอยู่ในนั้น ฉันต้องการยืนยันว่าลำดับไบนารีคือสิ่งที่ควรจะเป็น ฉันได้ลอง.equalsนอกเหนือจากนี้==แต่ก็ไม่ได้ผล

byte[] array = new BigInteger("1111000011110001", 2).toByteArray();
if (new BigInteger("1111000011110001", 2).toByteArray() == array){
    System.out.println("the same");
} else {
    System.out.println("different'");
}

คุณสามารถเปรียบเทียบสตริงโดยตรงได้หรือไม่?
วัตถุ

1
@ วัตถุ - เลขศูนย์นำหน้า นอกจากนี้สิ่งที่ String / BigInteger อาจเป็นเพียงวิธีหนึ่งในการแสดงคำถามเปรียบเทียบไบต์อาร์เรย์
Stephen C

คุณได้ลองใช้วิธี CompareTo หรือยัง? BTW ==เปรียบเทียบค่าดั้งเดิมเพียงแค่ fyi
ChriskOlson

คำถามที่เกี่ยวข้องเกี่ยวกับการเปรียบเทียบอาร์เรย์บางส่วน: stackoverflow.com/questions/16646967/…
Vadzim

คำตอบ:


169

ในตัวอย่างของคุณคุณมี:

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

เมื่อจัดการกับวัตถุ==ใน java เปรียบเทียบค่าอ้างอิง คุณกำลังตรวจสอบว่าการอ้างอิงไปยังอาร์เรย์ที่ส่งคืนมาtoByteArray()นั้นเหมือนกับการอ้างอิงที่มีอยู่arrayหรือไม่ซึ่งแน่นอนว่าไม่มีทางเป็นจริงได้ นอกจากนี้คลาสอาร์เรย์จะไม่แทนที่.equals()ดังนั้นลักษณะการทำงานจึงเป็นObject.equals()เพียงการเปรียบเทียบค่าอ้างอิงเท่านั้น

ในการเปรียบเทียบเนื้อหาของอาร์เรย์สองอาร์เรย์วิธีการเปรียบเทียบอาร์เรย์แบบคงที่จัดเตรียมโดยคลาสอาร์เรย์

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!");
}


11

Java ไม่โอเวอร์โหลดตัวดำเนินการดังนั้นโดยปกติคุณจะต้องมีเมธอดสำหรับประเภทที่ไม่ใช่พื้นฐาน ลองArrays.equals ()วิธีการ


11

คุณสามารถใช้ทั้งสองArrays.equals()และMessageDigest.isEqual(). สองวิธีนี้มีความแตกต่างกันบ้าง

MessageDigest.isEqual()เป็นวิธีการเปรียบเทียบค่าคงที่ของเวลาและArrays.equals()ไม่ใช่ค่าคงที่ของเวลาและอาจทำให้เกิดปัญหาด้านความปลอดภัยหากคุณใช้ในแอปพลิเคชันความปลอดภัย

สามารถอ่านรายละเอียดความแตกต่างได้ที่Arrays.equals () vs MessageDigest.isEqual ()


3

แน่นอนคำตอบที่ยอมรับของ Arrays.equal (byte [] แรกไบต์ [] วินาที) นั้นถูกต้อง ฉันชอบทำงานในระดับต่ำกว่า แต่ไม่พบฟังก์ชันที่มีประสิทธิภาพระดับต่ำเพื่อทำการทดสอบช่วงความเท่าเทียมกัน ฉันต้องแส้ของตัวเองถ้าใครต้องการ:

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;
}

นี่เป็นทางออกที่ดีสำหรับการทดสอบชุดย่อยของอาร์เรย์แทนที่จะเป็นทั้งชิ้น อย่างไรก็ตามโปรดทราบว่า Arrays.equals (byte [], byte []) ทำทุกอย่างที่คุณทำที่นี่ (ยกเว้นจัดการกับค่าสองค่าที่เป็นวัตถุเดียวกันได้อย่างมีประสิทธิภาพมากขึ้นและจัดการอาร์เรย์ว่างที่ส่งผ่านอย่างสง่างาม) เมื่อมีตัวเลือกให้ใช้การใช้งานไลบรารีมาตรฐานซึ่งชุมชนจะสนับสนุนหรือเขียนการใช้งานแบบกำหนดเองซึ่งฉันจะต้องสนับสนุนตลอดไปฉันจะเลือกแบบเดิมทุกครั้ง
Tom Dibble

4
คำตอบมีประโยชน์สำหรับกรณีการใช้งานที่หนึ่งมีอาร์เรย์สองอาร์เรย์และต้องการเปรียบเทียบช่วงของไบต์จากอาร์เรย์โดยไม่ต้องทำสำเนาอาร์เรย์ก่อน สำเนาอาร์เรย์เพิ่มค่าใช้จ่ายเพิ่มขยะและไม่จำเป็น สิ่งที่ฉันต้องการคือ memcmp สไตล์ c ระดับต่ำ () และสิ่งนี้เหมาะกับความต้องการ แน่นอน memcmp () ใช้อาร์กิวเมนต์ความยาวเพียง 1 อาร์กิวเมนต์ ฟังก์ชั่นนี้อยู่ใกล้พอ
Bamaco

2

เนื่องจากฉันต้องการเปรียบเทียบอาร์เรย์สองอาร์เรย์สำหรับการทดสอบหน่วยและฉันได้รับคำตอบนี้ฉันจึงคิดว่าสามารถแบ่งปันได้

คุณสามารถทำได้ด้วย:

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

  Assert.assertArrayEquals(array, secondArray);
}

และคุณสามารถตรวจสอบการเปรียบเทียบอาร์เรย์ในการยืนยัน JUnitสำหรับข้อมูลเพิ่มเติม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.