Câu hỏi Kiểm tra xem một danh sách có chứa phần tử từ phần tử khác không


Tôi có hai danh sách với các đối tượng khác nhau trong chúng.

List<Object1> list1;
List<Object2> list2;

Tôi muốn kiểm tra nếu phần tử từ list1 tồn tại trong list2, dựa trên thuộc tính cụ thể (Object1 và Object2 có (trong số những người khác), một thuộc tính lẫn nhau (với kiểu Long), có tên là attributeSame).

ngay bây giờ, tôi làm như thế này:

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

Nhưng tôi nghĩ rằng có một cách tốt hơn và nhanh hơn để làm điều này :) Ai đó có thể đề xuất nó?

Cảm ơn!


76
2017-08-03 13:08


gốc


trước tiên, khi bạn đặt hàng = true; sau đó chỉ đơn giản là phá vỡ; hoặc ra khỏi vòng lặp - Shubhansh
stackoverflow.com/questions/5187888/…. Hơn nữa, để tìm kiếm nhanh chóng, hãy thử sử dụng Tìm kiếm nhị phân và thay đổi DS của bạn để tính toán tình huống ... - Shubhansh
họ có chung một phụ huynh bên cạnh Object không? - Woot4Moo
@ Woot4Moo không, họ không - Ned


Các câu trả lời:


Điều này có thể được thực hiện với JDK cơ bản mà không sửa đổi các danh sách đầu vào trong một dòng

!Collections.disjoint(list1, list2);

160
2017-08-03 15:59



Điều này sẽ không trả về false vì cả hai đều là 2 đối tượng khác nhau? - Venki
À, không? Các phép kiểm tra rời rạc nếu không có đối tượng nào bằng () với nhau giữa hai bộ sưu tập. - Louis Wasserman
Ngoài ra, xin lưu ý rằng, đối với danh sách, đây sẽ là O (n * m); nếu bạn sẵn sàng sao chép list1 thành một Set trước khi so sánh, bạn sẽ nhận được O (n) + O (m), nghĩa là, O (n + m), với chi phí của một số RAM phụ; đó là vấn đề lựa chọn giữa tốc độ hoặc bộ nhớ. - Haroldo_OK
Wow! có vẻ như đang hoạt động - delive
Câu trả lời này không có ý nghĩa. Làm thế nào điều này đưa vào tài khoản mà OP muốn so sánh một giá trị cụ thể, duy nhất trong hai đối tượng? - Zephyr


Bạn có thể dùng Bộ sưu tập của Apache CommonsUtils:

if(CollectionUtils.containsAny(list1,list2)) {  
    // do whatever you want
} else { 
    // do other thing 
}  

Điều này giả định rằng bạn đã quá tải đúng chức năng bằng cho các đối tượng tùy chỉnh của bạn.


31
2017-08-03 13:19



Chết li, bạn tình. - alexander
đã 4 năm rồi và tôi cũng gọi một cách rõ ràng gói và chức năng. - Woot4Moo
Downvote cho commache apache khi có một giải pháp chỉ jdk - ohcibi
@ohcibi Java cũng có một trình ghi logger, bạn nên downvote những người gợi ý sử dụng Log4j và Log4j2 trong khi bạn đang ở đó. - Woot4Moo
@ Woot4Moo nó phụ thuộc. Không có lý do để downvote nếu có một lý do để sử dụng Log4j để giải quyết vấn đề OPS. Trong trường hợp này, apache commons sẽ đơn giản là vô ích, như trong 99% câu trả lời gợi ý commache apache. - ohcibi


một phương pháp của Collection có tên retainAll nhưng có một số tác dụng phụ cho bạn tài liệu tham khảo

Chỉ giữ lại các phần tử trong danh sách này được chứa trong   bộ sưu tập được chỉ định (hoạt động tùy chọn). Nói cách khác, loại bỏ   từ danh sách này tất cả các phần tử của nó không có trong   bộ sưu tập được chỉ định.

đúng nếu danh sách này thay đổi do cuộc gọi

Nó giống như

boolean b = list1.retainAll(list2);

8
2017-08-03 13:23





Câu trả lời Loius là chính xác, tôi chỉ muốn thêm một ví dụ:

listOne.add("A");
listOne.add("B");
listOne.add("C");

listTwo.add("D");
listTwo.add("E");
listTwo.add("F");      

boolean noElementsInCommon = Collections.disjoint(listOne, listTwo); // true

3
2018-02-19 16:57



Tôi nghĩ nếu bạn thêm phần tử 'A' vào danh sách thứ hai listTwo.add ("A"); mặc dù Collections.disjoint (listOne, listTwo); trả về true. - Sairam Kukadala


cách nhanh hơn sẽ cần thêm không gian.

Ví dụ:

  1. đặt tất cả các mục trong một danh sách vào một HashSet (bạn phải thực hiện hàm băm của chính mình để sử dụng object.getAttributeSame ())

  2. Đi qua danh sách khác và kiểm tra xem có mục nào nằm trong HashSet hay không.

Bằng cách này, mỗi đối tượng được truy cập nhiều nhất một lần. và HashSet đủ nhanh để kiểm tra hoặc chèn bất kỳ đối tượng nào trong O (1).


2
2017-08-03 13:20





Theo JavaDoc cho .contains(Object obj):

Trả về true nếu danh sách này chứa phần tử được chỉ định. Hơn   chính thức, trả về true nếu và chỉ khi danh sách này chứa ít nhất một   phần tử e sao cho (o == null? e == null: o.equals (e)).

Vì vậy, nếu bạn ghi đè .equals() cho đối tượng đã cho, bạn có thể thực hiện: if(list1.contains(object2))...

Nếu các phần tử sẽ là duy nhất (ví dụ: có các thuộc tính khác nhau), bạn có thể ghi đè lên .equals() và .hashcode() và lưu trữ mọi thứ trong HashSets. Điều này sẽ cho phép bạn kiểm tra xem có chứa phần tử khác trong thời gian không đổi không.


2
2017-08-03 13:13





để làm cho nó nhanh hơn, bạn có thể thêm giờ nghỉ; theo cách đó vòng lặp sẽ dừng nếu tìm thấy được đặt thành true:

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           //also do something  
           break;
       }
    }
    if(!found){
        //do something
    }
    found = false;
}

Nếu bạn có bản đồ thay cho các danh sách với các khóa là attributeSame, bạn có thể kiểm tra nhanh hơn cho một giá trị trong một bản đồ nếu có giá trị tương ứng trong bản đồ thứ hai hay không.


1
2017-08-03 13:10



Xin chào Tom, cảm ơn vì đã chú ý! Có, tôi đã quên "ngắt" trong khi nhập. Nhưng tôi đã suy nghĩ có thể có một số thuật toán, hoặc tôi nên thay đổi các danh sách này thành một số bộ sưu tập khác. - Ned
Tôi đã chỉnh sửa để trả lời o bình luận của bạn - Tom
không có bất cứ điều gì tốt hơn so với O (n * m)? - Woot4Moo
.getAttributeSame ()? - Manish
Việc triển khai phương thức getAttributeSame () từ Object1 và Object2 không được cung cấp, nhưng cũng không liên quan đến câu hỏi và câu trả lời; nó chỉ trả về một thuộc tính (attributeSame, một Long) mà cả hai lớp đều có. - Tom


Bạn có thể xác định loại dữ liệu bạn giữ không? nó là dữ liệu lớn? nó có được sắp xếp không? Tôi nghĩ rằng bạn cần phải xem xét các phương pháp tiếp cận hiệu quả khác nhau tùy thuộc vào dữ liệu.

Ví dụ: nếu dữ liệu của bạn lớn và không được phân loại, bạn có thể thử và lặp lại hai danh sách với nhau bằng chỉ mục và lưu trữ từng thuộc tính danh sách trong một trình trợ giúp danh sách khác. sau đó bạn có thể kiểm tra chéo bởi các thuộc tính hiện tại trong danh sách trợ giúp.

chúc may mắn

chỉnh sửa: và tôi sẽ không đề nghị quá tải bằng. nguy hiểm của nó và có lẽ chống lại ý nghĩa đối tượng oop của bạn.


0
2017-08-03 13:27





org.springframework.util.CollectionUtils

boolean containsAny(java.util.Collection<?> source, java.util.Collection<?> candidates)

Return true if any element in 'candidates' is contained in 'source'; otherwise returns false

0
2018-02-13 07:04