วิธีง่ายๆในการค้นหาว่ามีสองรายการที่แตกต่างกันมีองค์ประกอบที่เหมือนกันหรือไม่?


253

วิธีที่ง่ายที่สุดในการค้นหาคือถ้ารายการสองรายการมีองค์ประกอบเดียวกันในไลบรารี Java มาตรฐานหรือไม่

ไม่สำคัญว่าทั้งสองรายการจะเป็นอินสแตนซ์เดียวกันหรือไม่และไม่สำคัญว่าพารามิเตอร์ประเภทของรายการจะแตกต่างกันหรือไม่

เช่น

List list1
List<String> list2; 
// ... construct etc

list1.add("A");
list2.add("A"); 
// the function, given these two lists, should return true

อาจมีบางอย่างจ้องมองฉันในหน้าฉันรู้ :-)


แก้ไข: เพื่อชี้แจงฉันกำลังมองหาองค์ประกอบที่แน่นอนเดียวกันและจำนวนขององค์ประกอบในการสั่งซื้อ


องค์ประกอบต้องอยู่ในลำดับเดียวกันหรือไม่
Michael Myers

สิ่งนี้อาจไม่ส่งผลกระทบต่อคุณ แต่ระวังว่าชุดถาวรจำศีลบางครั้งไม่เคารพสัญญาเท่ากับ - ค้นหาดูopensource.atlassian.com/projects/hibernate/browse/HHH-3799
Pablojim

คำตอบ:


367

หากคุณสนใจคำสั่งซื้อให้ใช้วิธีเท่ากับ:

list1.equals(list2)

จาก javadoc:

เปรียบเทียบวัตถุที่ระบุกับรายการนี้เพื่อความเท่าเทียมกัน ส่งคืนจริงถ้าและถ้าวัตถุที่ระบุเป็นรายการทั้งสองรายการมีขนาดเท่ากันและคู่ขององค์ประกอบที่เกี่ยวข้องในรายการทั้งสองนั้นเท่ากัน (สององค์ประกอบ e1 และ e2 มีค่าเท่ากันถ้า (e1 == null? e2 == ว่าง: e1.equals (e2))) ในคำอื่น ๆ รายการสองรายการจะถูกกำหนดให้เท่ากันหากมีองค์ประกอบเดียวกันในลำดับเดียวกัน . คำจำกัดความนี้ทำให้มั่นใจได้ว่าวิธีการที่เท่าเทียมกันทำงานอย่างถูกต้องในการใช้งานที่แตกต่างกันของรายการอินเตอร์เฟซ

หากคุณต้องการตรวจสอบความเป็นอิสระของคำสั่งซื้อคุณสามารถคัดลอกองค์ประกอบทั้งหมดไปยังชุดและใช้เท่ากับในชุดผลลัพธ์:

public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

ข้อ จำกัด ของวิธีนี้คือไม่เพียง แต่ละเว้นคำสั่งเท่านั้น แต่ยังรวมถึงความถี่ขององค์ประกอบที่ซ้ำซ้อน ตัวอย่างเช่นหากlist1["A", "B", "A"] และlist2เป็น ["A", "B", "B"] Setวิธีการจะถือว่าพวกเขาเท่าเทียมกัน

หากคุณจำเป็นต้องมีความรู้สึกไวต่อการสั่งซื้อ แต่ละเอียดอ่อนต่อความถี่ของการทำซ้ำคุณสามารถ:

  • เรียงลำดับรายการทั้งสอง (หรือสำเนา) ก่อนที่จะเปรียบเทียบพวกเขาเช่นเดียวกับที่ทำในคำตอบนี้กับคำถามอื่น
  • หรือคัดลอกองค์ประกอบทั้งหมดไปที่Multiset

54
คุณไม่สามารถใช้ containAll หากคุณต้องการตรวจสอบคำสั่งซื้อโดยอิสระหรือไม่?
laz

6
ฉันไม่รู้เกี่ยวกับรายละเอียดการใช้งานของ containAll แต่ดูเหมือนว่าอาจไม่ดี หากมีการโทรทั้งหมดมี () ซ้ำไปซ้ำมาคุณจะมี O (n ^ 2) alg ชุดโดยรวมควรเป็น O (nlogn)
Tom

6
จริงๆแล้วถ้าเซตนั้นจะเป็น O (nlogn) อีกวิธีหนึ่งคือการเรียก Collections.sort () ในรายการแล้วใช้เท่ากับ หากคุณต้องการรักษาความสงบเรียบร้อยไว้คุณจะต้องคัดลอกรายการและอาจมีราคาแพงและสนับสนุนวิธีแก้ไขปัญหา ... ดังนั้นคุณต้องคิดถึงสถานการณ์ของคุณ :-)
Tom

1
@amischiefr: คุณแนะนำ O (n ^ 2) ว่าดีที่สุดที่คุณทำได้หรือไม่?
Tom

8
@Dennis การตรวจสอบขนาดใช้งานได้จริงถ้าคุณรู้ว่าแต่ละรายการมีองค์ประกอบที่แตกต่างกันเท่านั้น ตัวอย่างเช่นกำหนดa = [x, y, x]และb = [x, y, z]จากนั้นมีขนาดเท่ากันและb.containsAll(a)จะกลับมาจริง แต่มีองค์ประกอบไม่ได้อยู่ในb a
Laurence Gonsalves

95

ฉันโพสต์สิ่งต่าง ๆ ในความคิดเห็นฉันคิดว่ามันรับประกันคำตอบของตัวเอง

ตามที่ทุกคนพูดที่นี่การใช้เท่ากับ () ขึ้นอยู่กับลำดับ หากคุณไม่สนใจคำสั่งซื้อคุณมี 3 ตัวเลือก

ตัวเลือกที่ 1

containsAll()ใช้ ตัวเลือกนี้ไม่เหมาะอย่างยิ่งในความคิดของฉันเพราะมันมีประสิทธิภาพกรณีที่เลวร้ายที่สุด O (n ^ 2)

ตัวเลือก 2

มีสองรูปแบบสำหรับสิ่งนี้:

2a)หากคุณไม่สนใจเกี่ยวกับการรักษาลำดับรายการของคุณ ... ใช้Collections.sort()ทั้งสองรายการ equals()จากนั้นใช้ นี่คือ O (nlogn) เพราะคุณทำสองประเภทแล้วเปรียบเทียบ O (n)

2b)หากคุณต้องการรักษาลำดับของรายการคุณสามารถคัดลอกทั้งสองรายการก่อน จากนั้นคุณสามารถใช้โซลูชัน2aทั้งในรายการที่คัดลอก อย่างไรก็ตามการทำเช่นนี้อาจไม่น่าสนใจหากการทำสำเนามีราคาแพงมาก

นี่นำไปสู่:

ตัวเลือก 3

หากความต้องการของคุณเหมือนกับภาค2bแต่การทำสำเนาแพงเกินไป คุณสามารถใช้ TreeSet เพื่อทำการเรียงลำดับสำหรับคุณ ดัมพ์แต่ละรายการเป็น TreeSet ของมันเอง มันจะถูกจัดเรียงในชุดและรายการเดิมจะยังคงอยู่ จากนั้นทำการequals()เปรียบเทียบทั้งสองTreeSetเอส TreeSetss สามารถสร้างขึ้นใน O (nlogn) เวลาและequals()เป็น O (n)

เลือก :-)

แก้ไข:ฉันเกือบลืมคำเตือนเดียวกับที่ Laurence Gonsalvesชี้ให้เห็น การใช้ TreeSet จะกำจัดรายการที่ซ้ำกัน หากคุณสนใจรายการที่ซ้ำกันคุณจะต้องมีชุดข้อมูลหลายชุดที่เรียงลำดับ


หากคุณสนใจรายการที่ซ้ำกันคุณสามารถทดสอบได้ว่าขนาดของคอลเลกชันจะเท่ากันก่อนการทดสอบอื่น ๆ
laz

โดยเฉพาะอย่างยิ่งหากมีการซ้ำซ้อนระบุความไม่เท่าเทียมกันขนาดของรายการจะต้องเหมือนกันก่อนการตรวจสอบความเท่าเทียมกันใด ๆ มีโอกาสที่จะประสบความสำเร็จ
laz

7
@laz: การตรวจสอบขนาดจะไม่ทำงานหากองค์ประกอบที่แตกต่างกันถูกทำซ้ำในสองรายการ เช่น: [A, A, B] กับ [A, B, B] มีขนาดเท่ากัน
Laurence Gonsalves

@ Laurence: ฉันยอมรับว่าโพสต์ของ laz ค่อนข้างสับสน (ฉันอ่านสองสามครั้งก่อนที่ฉันจะเข้าใจ) ฉันคิดว่าเขากำลังพยายามให้ "ทางลัด" สำหรับกรณีพิเศษเมื่อมี 2 เงื่อนไข: (1) เรื่องที่ซ้ำกันและ (2) ขนาดรายการแตกต่างกัน ในตัวอย่างของคุณฉันคิดว่าลาซยังคงบอกว่าจำเป็นต้องทำการตรวจสอบทั้งหมดที่เราพูดถึง (อย่างน้อยนั่นก็เป็นวิธีที่ฉันอ่าน) หากการทำซ้ำไม่สำคัญคุณจะไม่สามารถใช้ขนาดเป็นการตรวจสอบกรณีพิเศษ แต่เมื่อ 2 เงื่อนไขค้างไว้คุณสามารถพูดว่า "if (list1.size ()! = list2.size ()) return false;.
Tom

9
มีทั้งหมดฉันคิดว่าจะให้คำตอบที่ผิดคุณจะต้องมีทั้งสองวิธี a.containsAll(b) && b.containsAll(a)
Richard Tingle

24

หากคุณกำลังใช้ (หรือมีความสุขที่จะใช้) คอลเลกชัน Apache Commons คุณสามารถใช้CollectionUtils.isEqualCollectionซึ่ง "คืนค่าจริงถ้า if คอลเลกชันที่กำหนดมีองค์ประกอบเดียวกันกับที่มีความสำคัญเหมือนกันทุกประการ"


การใช้งาน hashmap ที่ดีมาก รันไทม์ควรเป็น O (n) และหากมีองค์ประกอบที่ซ้ำจำนวนมากจะใช้หน่วยความจำขั้นต่ำในการติดตาม (โดยทั่วไปจะติดตามความถี่ (ความสำคัญ)) ขององค์ประกอบโดยใช้แผนที่สำหรับการรวบรวมแต่ละชุด ข้อเสียคือมีการใช้หน่วยความจำ O (n) เพิ่มเติม
Muhd

17

ไปงานปาร์ตี้ช้ามาก แต่ต้องการเพิ่มการตรวจสอบความปลอดภัยแบบ null นี้:

Objects.equals(list1, list2)

8

ฉันรู้ว่านี่เป็นเธรดเก่า แต่ไม่มีคำตอบอื่นใดที่แก้ไขกรณีการใช้งานของฉันได้อย่างสมบูรณ์ (ฉันเดาว่า Multiset ของ Guava อาจทำแบบเดียวกัน แต่ไม่มีตัวอย่างที่นี่) โปรดแก้ตัวการจัดรูปแบบของฉัน ฉันยังใหม่ต่อการโพสต์ในการแลกเปลี่ยนสแต็ค นอกจากนี้แจ้งให้เราทราบหากมีข้อผิดพลาดใด ๆ

ให้บอกว่าคุณมีList<T>a และList<T>b และคุณต้องการตรวจสอบว่าพวกเขาจะเท่ากับเงื่อนไขต่อไปนี้:

1) O (n) เวลาทำงานที่คาดหวัง
2) ความเสมอภาคหมายถึง: สำหรับองค์ประกอบทั้งหมดใน a หรือ b จำนวนครั้งที่องค์ประกอบเกิดขึ้นใน a เท่ากับจำนวนครั้งที่องค์ประกอบเกิดขึ้นใน b ความเท่าเทียมกันขององค์ประกอบหมายถึง T.equals ()

private boolean listsAreEquivelent(List<? extends Object> a, List<? extends Object> b) {
    if(a==null) {
        if(b==null) {
            //Here 2 null lists are equivelent. You may want to change this.
            return true;
        } else {
            return false;
        }
    }
    if(b==null) {
        return false;
    }
    Map<Object, Integer> tempMap = new HashMap<>();
    for(Object element : a) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            tempMap.put(element, 1);
        } else {
            tempMap.put(element, currentCount+1);
        }
    }
    for(Object element : b) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            return false;
        } else {
            tempMap.put(element, currentCount-1);
        }
    }
    for(Integer count : tempMap.values()) {
        if(count != 0) {
            return false;
        }
    }
    return true;
}

เวลาทำงานคือ O (n) เพราะเรากำลังทำการแทรก O (2 * n) ลงใน hashmap และเลือก hashmap O (3 * n) ฉันยังไม่ได้ทดสอบรหัสนี้อย่างสมบูรณ์ดังนั้นโปรดระวัง :)

//Returns true:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","A"));
listsAreEquivelent(null,null);
//Returns false:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),null);

5

ลองใช้เวอร์ชั่นนี้ซึ่งไม่จำเป็นต้องมีคำสั่งเหมือนกัน แต่รองรับได้หลายค่า จะจับคู่ก็ต่อเมื่อแต่ละคนมีค่าเท่ากัน

public boolean arraysMatch(List<String> elements1, List<String> elements2) {
    // Optional quick test since size must match
    if (elements1.size() != elements2.size()) {
        return false;
    }
    List<String> work = newArrayList(elements2);
    for (String element : elements1) {
        if (!work.remove(element)) {
            return false;
        }
    }
    return work.isEmpty();
}

work.remove (องค์ประกอบ) คือ O (n) ดังนั้นโซลูชันนี้คือ O (n ^ 2)
Andrew

หรือ O (n1 * n2) ซึ่งเป็นประเภทเดียวกัน
Lee Meador

ฉันยังใช้กลยุทธ์เดียวกันเพราะมันจัดการทุกสถานการณ์และขนาดของคอลเล็กชั่นนั้นไม่ใหญ่เท่านั้น O (n ^ 2) ไม่สำคัญ
Naresh Joshi

3

วิธีการที่เท่าเทียมกันในรายการจะทำเช่นนี้รายการจะถูกเรียงลำดับดังนั้นเพื่อให้เท่ากับสองรายการจะต้องมีองค์ประกอบเดียวกันในลำดับเดียวกัน

return list1.equals(list2);

3
รายการจะไม่ถูกเรียงลำดับเว้นแต่คุณจะเรียงลำดับ
Michael Myers

เฮ้อ @ ตัวเอง ช่างเป็นคำตอบที่ชัดเจน คุณรู้ว่ามันนานเกินไปต่อวันเมื่อคุณไม่สามารถกด Ctrl + F เว็บเพจได้อีกต่อไป :)
Grundlefleck

2
@mmyers: ไม่มีการเรียงลำดับรายการในรายการเว้นแต่คุณจะเรียงลำดับ รายการตัวเองมีการเรียงลำดับโดยนัยของรายการ (ตามดัชนี) ซึ่งจะไม่เปลี่ยนแปลงเว้นแต่คุณจะเปลี่ยนรายการในรายการ (เทียบกับชุดหรือคอลเลกชันที่มีไม่ได้รับประกันการสั่งซื้อที่สอดคล้องกันถ้าคุณย้ำผ่านพวกเขาสองครั้ง)
เจสัน S

ฉันคิดว่าสิ่งที่ daveb หมายถึงการเรียงลำดับรายการคำพูดคือ List.equals ใช้ลำดับขององค์ประกอบเข้าสู่การพิจารณาเพื่อกำหนดความเท่าเทียมกัน ดู Javadoc
laz

2
สิ่งที่ฉันหมายถึงคือรายการที่มี {"A", "B"} และรายการที่มี {"B", "A"} จะไม่เท่ากันกับวิธีนี้ นั่นอาจเป็นสิ่งที่ตั้งใจ แต่ฉันต้องการตรวจสอบให้แน่ใจว่าไม่มีใครมองเห็นมัน
Michael Myers

3

วิธีแก้ปัญหาสำหรับกรณีที่รายการทั้งสองมีองค์ประกอบเดียวกัน แต่เรียงลำดับต่างกัน:

public boolean isDifferentLists(List<Integer> listOne, List<Integer> listTwo) {
    if(isNullLists(listOne, listTwo)) {
        return false;
    }

    if (hasDifferentSize(listOne, listTwo)) {
        return true;
    }

    List<Integer> listOneCopy = Lists.newArrayList(listOne);
    List<Integer> listTwoCopy = Lists.newArrayList(listTwo);
    listOneCopy.removeAll(listTwoCopy);

    return CollectionUtils.isNotEmpty(listOneCopy);
}

private boolean isNullLists(List<Integer> listOne, List<Integer> listTwo) {
    return listOne == null && listTwo == null;
}

private boolean hasDifferentSize(List<Integer> listOne, List<Integer> listTwo) {
    return (listOne == null && listTwo != null) || (listOne != null && listTwo == null) || (listOne.size() != listTwo.size());
}

2
ฉันคิดว่าคุณไม่จำเป็นต้องคัดลอก listTwo
AjahnCharles

1
คุณอาจต้องการทราบสาเหตุที่คุณใช้removeAll()แทนcontainsAll()(ความเข้าใจของฉันคือถ้า listTwo มีรายการซ้ำที่มีอยู่เพียงครั้งเดียวใน listOne วิธี containAll () จะรายงานรายการไม่ถูกต้องอย่างไม่ถูกต้อง
AjahnCharles

3

คำตอบของทอมนั้นยอดเยี่ยมฉันเห็นด้วยอย่างยิ่งกับคำตอบของเขา!

ประเด็นที่น่าสนใจของคำถามนี้คือไม่ว่าคุณจะต้องการ Listประเภทของตัวเองและการเรียงลำดับโดยธรรมชาติ

ถ้าไม่ใช่คุณสามารถลดระดับIterableหรือCollectionทำให้คุณมีความยืดหยุ่นในการส่งผ่านโครงสร้างข้อมูลที่เรียงลำดับตามเวลาที่แทรกแทนที่จะเป็นเวลาที่คุณต้องการตรวจสอบ

หากคำสั่งไม่สำคัญ (และคุณไม่ได้มีองค์ประกอบที่ซ้ำกัน) Setพิจารณาการใช้

หากการสั่งซื้อมีความสำคัญ แต่ถูกกำหนดโดยเวลาที่ใส่ (และคุณไม่มีรายการที่ซ้ำกัน) ให้พิจารณาชุดLinkedHashSetที่คล้ายกับ TreeSet แต่เรียงลำดับตามเวลาที่แทรก (จะนับซ้ำกัน) นอกจากนี้ยังให้O(1)สิทธิ์การเข้าถึงที่O(log n)จำกัด ด้วย


2

รหัสตัวอย่าง:

public static '<'T'>' boolean isListDifferent(List'<'T'>' previousList,
        List'<'T'>' newList) {

    int sizePrevoisList = -1;
    int sizeNewList = -1;

    if (previousList != null && !previousList.isEmpty()) {
        sizePrevoisList = previousList.size();
    }
    if (newList != null && !newList.isEmpty()) {
        sizeNewList = newList.size();
    }

    if ((sizePrevoisList == -1) && (sizeNewList == -1)) {
        return false;
    }

    if (sizeNewList != sizePrevoisList) {
        return true;
    }

    List n_prevois = new ArrayList(previousList);
    List n_new = new ArrayList(newList);

    try {
        Collections.sort(n_prevois);
        Collections.sort(n_new);
    } catch (ClassCastException exp) {
        return true;
    }

    for (int i = 0; i < sizeNewList; i++) {
        Object obj_prevois = n_prevois.get(i);
        Object obj_new = n_new.get(i);
        if (obj_new.equals(obj_prevois)) {
            // Object are same
        } else {
            return true;
        }
    }

    return false;
}

2

นอกเหนือจากคำตอบของลอเรนซ์หากคุณต้องการทำให้เป็นโมฆะปลอดภัย:

private static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    if (list1 == null)
        return list2==null;
    if (list2 == null)
        return list1 == null;
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

1
คุณสามารถทำให้การตรวจสอบง่ายขึ้น:if (list1 == null) return list2==null; if (list2 == null) return false;
Xerus

ไม่ทำงานหากรายการนั้นเป็น [a, a, b, c] & [a, b, c] และจะกลับมาจริงเว้นแต่ว่าจะเพิ่มการตรวจสอบเพิ่มเติมเพื่อให้แน่ใจว่าขนาดของรายการนั้นเหมือนกัน
Venkat Madhav

2
list1.equals(list2);

ถ้ารายการของคุณมีคลาส MyClass แบบกำหนดเองคลาสนี้ต้องแทนที่equalsฟังก์ชัน

 class MyClass
  {
  int field=0;
  @0verride
  public boolean equals(Object other)
        {
        if(this==other) return true;
        if(other==null || !(other instanceof MyClass)) return false;
        return this.field== MyClass.class.cast(other).field;
        }
  }

หมายเหตุ: หากคุณต้องการทดสอบเท่ากับ java.util.Set แทนที่จะเป็น a java.util.Listวัตถุของคุณจะต้องแทนที่hashCode ฟังก์ชัน


1
ควรบรรทัด: return this.field == MyClass.class.cast (อื่น ๆ ); จะได้รับ this.field == MyClass.class.cast (อื่น ๆ ) .field;
alpere

@alpere โอ้! คุณถูก ! ฉันจะแก้ไขมัน ขอบคุณมาก!
ปิแอร์


0

คุณสามารถใช้ไลบรารี org.apache.commons.collections ของ Apache ได้ที่: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/ListUtils.html

public static boolean isEqualList(java.util.Collection list1,
                              java.util.Collection list2)

สิ่งนี้ยังต้องการองค์ประกอบของรายการที่จะอยู่ในลำดับเดียวกัน
josh-cain

คุณสามารถเรียงลำดับรายการก่อนทำการเปรียบเทียบ
David Zhao

แน่นอนว่าคุณสามารถทำตามประเภทที่เก็บไว้ในรายการหรือเรียงลำดับได้ (หรือคุณมีการตั้งค่าตัวเปรียบเทียบ) อย่างไรก็ตามอัลกอริทึมการใช้งาน Apache ไม่แตกต่างจาก list1.equals ปกติ (list2) ยกเว้นการเป็นแบบสแตติก ฉันเห็นว่าฉันเข้าใจผิดไปตรงไหนและจริง ๆ แล้วมันคือการถามวิธีเปรียบเทียบรายการในลำดับเดียวกัน ความผิดฉันเอง!
josh-cain

@DavidZhao: ลิงก์ตาย
Aniket Kulkarni


0

ตรวจสอบว่ารายการทั้งสองไม่ใช่โมฆะ หากขนาดแตกต่างกันรายการเหล่านี้จะไม่เท่ากัน สร้างแผนที่ที่ประกอบด้วยองค์ประกอบรายการเป็นปุ่มและรายการซ้ำเป็นค่าและเปรียบเทียบแผนที่

สมมติฐานถ้าทั้งสองรายการเป็นโมฆะฉันถือว่าพวกเขาเท่ากัน

private boolean compareLists(List<?> l1, List<?> l2) {
    if (l1 == null && l2 == null) {
        return true;
    } else if (l1 == null || l2 == null) {
        return false;
    }

    if (l1.size() != l2.size()) {
        return false;
    }

    Map<?, Integer> m1 = toMap(l1);
    Map<?, Integer> m2 = toMap(l2);

    return m1.equals(m2);
}

private Map<Object, Integer> toMap(List<?> list) {
    //Effective size, not to resize in the future.
    int mapSize = (int) (list.size() / 0.75 + 1);
    Map<Object, Integer> map = new HashMap<>(mapSize);

    for (Object o : list) {
        Integer count = map.get(o);
        if (count == null) {
            map.put(o, 1);
        } else {
            map.put(o, ++count);
        }
    }

    System.out.println(map);
    return map;
}

โปรดทราบว่าควรกำหนดวิธีการเท่ากับอย่างถูกต้องสำหรับวัตถุเหล่านี้ https://stackoverflow.com/a/24814634/4587961


1
คุณคิดว่าองค์ประกอบไม่สามารถนำเสนอจำนวนครั้งที่แตกต่างกันในแต่ละรายการเช่น[x, x, y]vs [x, y, y]จะกลับมาจริงกับการใช้งานของคุณ
AjahnCharles

@ CodeConfident ขอบคุณมาก! ฉันอัพเดตคำตอบแล้ว ฉันจะใช้เหมา!
Yan Khonski

-2

ขึ้นอยู่กับว่าคุณใช้คลาส List List อะไร AbstractCollection คลาสนามธรรมมีวิธีที่เรียกว่า containAll (Collection) ที่ใช้คอลเลกชันอื่น (List เป็นคอลเลกชัน) และ:

ผลตอบแทนจริงถ้าคอลเลกชันนี้มีองค์ประกอบทั้งหมดในคอลเลกชันที่ระบุ

ดังนั้นหากมีการส่ง ArrayList ในคุณสามารถเรียกใช้เมธอดนี้เพื่อดูว่าเหมือนกันหรือไม่

       List foo = new ArrayList();
    List bar = new ArrayList();
    String str = "foobar";

    foo.add(str);
    bar.add(str);

    foo.containsAll(bar);

เหตุผลสำหรับ containAll () เป็นเพราะมันวนซ้ำผ่านรายการแรกที่ค้นหาการจับคู่ในรายการที่สอง ดังนั้นหากพวกเขาออกคำสั่งเท่ากับ () จะไม่หยิบมันขึ้นมา

แก้ไข: ฉันแค่ต้องการแสดงความคิดเห็นที่นี่เกี่ยวกับเวลาทำงานตัดจำหน่ายในการดำเนินการตัวเลือกต่าง ๆ ที่นำเสนอ เวลาทำงานสำคัญหรือไม่ แน่ใจ มันเป็นสิ่งเดียวที่คุณควรพิจารณา? เลขที่

ค่าใช้จ่ายในการคัดลอกทุกองค์ประกอบจากรายการของคุณลงในรายการอื่นต้องใช้เวลาและมันยังใช้หน่วยความจำที่ดี (เพิ่มประสิทธิภาพหน่วยความจำที่คุณใช้เป็นสองเท่า)

ดังนั้นหากหน่วยความจำใน JVM ของคุณไม่ได้เป็นข้อกังวล (ซึ่งโดยทั่วไปควรเป็น) คุณก็ยังต้องพิจารณาเวลาที่ใช้ในการคัดลอกทุกองค์ประกอบจากสองรายการไปยัง TreeSets สองชุด โปรดจำไว้ว่ามันกำลังเรียงลำดับทุกองค์ประกอบเมื่อมันเข้ามา

คำแนะนำสุดท้ายของฉัน? คุณต้องพิจารณาชุดข้อมูลของคุณและจำนวนองค์ประกอบที่คุณมีในชุดข้อมูลของคุณและขนาดวัตถุแต่ละชิ้นในชุดข้อมูลของคุณก่อนที่คุณจะตัดสินใจได้ดี เล่นกับพวกเขาสร้างหนึ่งวิธีและดูว่าอันไหนเร็วกว่า มันเป็นการออกกำลังกายที่ดี


2
มันจะไม่ต้องเป็น foo.containers ทั้งหมด (บาร์) && bar.containers ทั้งหมด (foo); ?
คาร์ล Manaster

ไม่มันผ่านทุกองค์ประกอบใน foo และดูว่าแถบมีองค์ประกอบนั้นหรือไม่ จากนั้นตรวจสอบให้แน่ใจว่ามีความยาวเท่ากันในสองรายการ หากทุก ๆ foo มีองค์ประกอบอยู่ในแถบเช่นนั้น foo.element == bar.element และ foo.length == bar.length จะมีองค์ประกอบเดียวกัน
amischiefr

เราจะรู้ได้อย่างไรว่ามีการรับประกันประสิทธิภาพหรือไม่? หรือว่านี่คือ O (n ^ 2)?
Tom

เช่นเดียวกับอาเรย์อื่น ๆ ที่วนซ้ำผ่านการค้นหาองค์ประกอบที่ตรงกันเวลาทำงานที่เลวร้ายที่สุดจะเป็น O (n ^ 2) ในกรณีนี้ดูเหมือนว่าการติดตั้งใช้งานจริงซ้ำผ่านองค์ประกอบหนึ่งครั้งในการค้นหาการจับคู่ ฉันจะไม่คาดเดาเกี่ยวกับเวลาทำงานที่ตัดจำหน่าย แต่ใช่กรณีที่แย่ที่สุดคือ O (n ^ 2)
amischiefr

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