มี 'ชุดใด ๆ ' สำหรับชุด Java หรือไม่


307

ฉันมีสองชุด A และ B ประเภทเดียวกัน

ฉันต้องหาว่า A มีองค์ประกอบใด ๆ จากเซต B หรือไม่

อะไรจะเป็นวิธีที่ดีที่สุดในการทำสิ่งนั้นโดยไม่ทำซ้ำในฉาก? ห้องสมุดตลาดหลักทรัพย์ได้contains(object)และแต่ไม่containsAll(collection)containsAny(collection)


4
คุณกำลังพยายามหลีกเลี่ยงการวนซ้ำด้วยเหตุผลด้านประสิทธิภาพหรือเพื่อความสะอาดของรหัส?
yshavit

คำตอบ:


527

จะไม่Collections.disjoint(A, B)ทำงานเหรอ จากเอกสาร:

ส่งคืนtrueถ้าคอลเล็กชันที่ระบุสองรายการไม่มีองค์ประกอบที่เหมือนกัน

ดังนั้นเมธอดจะส่งคืนfalseหากคอลเล็กชันมีองค์ประกอบทั่วไปใด ๆ


17
ชอบที่นี่เพื่อแก้ไขปัญหาอื่น ๆ เพราะมันไม่ได้แก้ไขชุดใดชุดหนึ่งหรือสร้างใหม่
devconsole

7
และเป็นมาตรฐาน JRE และทำงานร่วมกับคอลเลกชันใด ๆ ไม่เพียง แต่ตั้งค่า
ปิแอร์เฮนรี่

4
ฉันไม่คิดว่ามันจะเร็วที่สุดมันจะไม่ลัดวงจรเมื่อพบองค์ประกอบแรกของทางแยก
Ben Horner

7
ที่จริงแล้วมันจะลัดวงจรทันทีที่พบองค์ประกอบทั่วไปตัวแรก
Xipo

3
@Xipo ถูกต้อง ตรวจสอบgrepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/…
Lluis Martinez

156

Stream::anyMatch

ตั้งแต่ Java 8 Stream::anyMatchคุณสามารถใช้

setA.stream().anyMatch(setB::contains)

1
นี่คือสิ่งที่ฉันกำลังมองหา! ขอบคุณ :-) ฉันยังไม่รู้ว่าคุณสามารถใช้ตัวแปรด้วย :: ไวยากรณ์!
dantiston

1
@ พลิกผันคุณช่วยอธิบายว่าเกิดอะไรขึ้นใน anyMatch ได้บ้าง
Cristiano

7
@ Cristiano ที่นี่anyMatchจะสตรีมองค์ประกอบทั้งหมดจากsetAและโทรหาsetB.contains()พวกเขาทั้งหมด หากส่งคืน "ความจริง" สำหรับองค์ประกอบใด ๆ นิพจน์โดยรวมจะประเมินค่าเป็นจริง หวังว่านี่จะช่วยได้
Alex Vulaj


31

วิธีที่ดีในการดำเนินการ containsAny สำหรับชุดที่ใช้ฝรั่งSets.intersection ()

containsAnyจะคืนค่า a booleanดังนั้นการโทรจึงดูเหมือนว่า:

Sets.intersection(set1, set2).isEmpty()

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


3
ข้อเสียเพียงอย่างเดียวของการใช้วิธีนี้คือคุณต้องรวมไลบรารีฝรั่ง ซึ่งฉันคิดว่ามันไม่ได้เป็นข้อเสียเพราะ API ของ Google คอลเลกชันนั้นแข็งแกร่งมาก
Mohammad Adnan

@DidierL ที่สุดของคอลเลกชันฝรั่งฟังก์ชั่นยูทิลิตี้รวมถึงคนนี้กลับมามองเห็นวิวของโครงสร้างข้อมูล ดังนั้นจึงไม่มี "การสร้างชุด" ที่ต้องกังวลในกรณีนี้ การดำเนินงานเป็นที่น่าสนใจในการอ่านที่นี่และ / หรือดู Javadoc: google.github.io/guava/releases/21.0/api/docs/com/google/common/...
ฉัตร

@MohammadAdnan ข้อเสียอีกอย่างคือมันคำนวณการตัดกันเต็ม - ถ้า set1 และ set2 มีขนาดใหญ่มากนี่จะเป็นทรัพยากรที่เข้มข้นมากขึ้น (ทั้ง CPU และหน่วยความจำฉลาด) มากกว่าการตรวจสอบว่าพวกเขามีรายการที่เหมือนกัน
Marxama


16

ฉันใช้ org.apache.commons.collections.CollectionUtils

CollectionUtils.containsAny(someCollection1, someCollection2)

นั้นคือทั้งหมด! ผลตอบแทนจริงถ้าอย่างน้อยหนึ่งองค์ประกอบอยู่ในคอลเลกชันทั้งสอง

ใช้งานง่ายและชื่อของฟังก์ชั่นมีการชี้นำมากกว่า


5

ใช้retainAll()ในชุดอินเตอร์เฟส วิธีนี้จะให้จุดตัดขององค์ประกอบทั่วไปในทั้งสองชุด ดูเอกสาร API สำหรับข้อมูลเพิ่มเติม


หากจุดที่หลีกเลี่ยงการวนซ้ำนั้นมีประสิทธิภาพretainAllอาจไม่ช่วยได้ การใช้งานในAbstractCollectioniterates
yshavit

1
yshavit ถูกต้อง เนื่องจาก OP กำลังมองหาว่ามีองค์ประกอบใดบ้างในทั้งสองชุดอัลกอริทึมที่เหมาะสมจะมีO(1)เวลาทำงานในกรณีที่ดีที่สุดในขณะที่retainAllจะมีบางสิ่งบางอย่างตามเส้นของO(N)(มันจะขึ้นอยู่กับขนาดเพียง 1 ชุด) เวลาทำงานที่ดีที่สุด
Zéychin

3

ฉันขอแนะนำให้สร้าง a HashMapจาก set A จากนั้นวนซ้ำผ่าน set B และตรวจสอบว่าองค์ประกอบของ B ใด ๆ อยู่ใน A สิ่งนี้จะทำงานในO(|A|+|B|)เวลา (เนื่องจากไม่มีการชน) ในขณะที่retainAll(Collection<?> c)ต้องทำงานในO(|A|*|B|)เวลา


3

มีวิธีคร่าวๆเล็กน้อยในการทำเช่นนั้น ถ้าหากว่าชุด A มีองค์ประกอบของ B บางอย่างมากกว่าการโทร

A.removeAll(B)

จะแก้ไขชุด A ในสถานการณ์นี้ removeAll จะส่งคืนจริง (ตามที่ระบุไว้ที่removeAll docs ) แต่คุณอาจไม่ต้องการแก้ไขชุด A ดังนั้นคุณอาจคิดว่าจะทำสำเนาเหมือนอย่างนี้:

new HashSet(A).removeAll(B)

และค่าส่งคืนจะเป็นจริงหากเซตไม่ชัดเจนนั่นคือมีจุดตัดที่ไม่ว่างเปล่า

ดูที่Apache Commons Collections


2

คุณสามารถใช้retainAllวิธีการและได้รับการจุดตัดของสองชุดของคุณ


ในกรณีส่วนใหญ่จำเป็นต้องเก็บชุดต้นฉบับไว้ดังนั้นในการใช้งานretainAllจำเป็นต้องทำสำเนาชุดต้นฉบับ จากนั้นก็จะมีประสิทธิภาพมากขึ้นในการใช้งานHashSetตามข้อเสนอแนะZéychin
Petr Pudlák

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