So sánh hai danh sách trong Java


92

Tôi có hai danh sách (không phải danh sách java, bạn có thể nói là hai cột)

Ví dụ

**List 1**            **Lists 2**
  milan                 hafil
  dingo                 iga
  iga                   dingo
  elpha                 binga
  hafil                 mike
  meat                  dingo
  milan
  elpha
  meat
  iga                   
  neeta.peeta    

Tôi muốn một phương thức trả về bao nhiêu phần tử giống nhau. Đối với ví dụ này, nó phải là 3 và nó sẽ trả về cho tôi các giá trị tương tự của cả danh sách và các giá trị khác nhau.

Tôi có nên sử dụng hashmap nếu có thì phương pháp nào để nhận được kết quả của tôi?

Xin vui lòng giúp đỡ

PS: Không phải là bài tập ở trường đâu :) Nên chỉ cần bạn hướng dẫn là đủ


Xin gợi ý cho bất kỳ cấu trúc dữ liệu trong danh sách không phải là danh sách java hoặc hashmap hoặc bất kỳ cấu trúc dữ liệu
user238384

1
Hãy chắc chắn suy nghĩ về những gì bạn nên làm trong những trường hợp ngoại lệ. Danh sách có thể chứa cùng một giá trị hai lần không? Nếu vậy, nếu "dingo" có trong cả hai danh sách hai lần, thì điều đó có được tính là hai phần tử chung hay chỉ một phần tử?
JavadocMD

Bạn có thể sửa đổi một trong các Danh sách không?
Anthony Forloney

chỉnh sửa như thế nào ?? Có, mỗi danh sách có thể chứa các giá trị tương tự nhiều lần
dùng238384

Phải có một liên kết chỉnh sửa nhỏ ngay sau câu hỏi, bên dưới các thẻ.
OscarRyz

Câu trả lời:


159

BIÊN TẬP

Đây là hai phiên bản. Một sử dụng ArrayListvà một sử dụng khácHashSet

So sánh chúng và tạo phiên bản của riêng bạn từ đó, cho đến khi bạn nhận được thứ mình cần.

Điều này sẽ đủ để bao gồm:

PS: Không phải là bài tập ở trường đâu :) Nên chỉ cần bạn hướng dẫn là đủ

một phần của câu hỏi của bạn.

tiếp tục với câu trả lời ban đầu:

Bạn có thể sử dụng một java.util.Collection và / hoặc java.util.ArrayListcho điều đó.

Các retainAll phương pháp nào sau đây:

Chỉ giữ lại các phần tử trong bộ sưu tập này có trong bộ sưu tập được chỉ định

xem mẫu này:

import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;

public class Repeated {
    public static void main( String  [] args ) {
        Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
        Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));

        listOne.retainAll( listTwo );
        System.out.println( listOne );
    }
}

BIÊN TẬP

Đối với phần thứ hai (các giá trị tương tự), bạn có thể sử dụng phương thức removeAll :

Xóa tất cả các phần tử của bộ sưu tập này cũng có trong bộ sưu tập được chỉ định.

Phiên bản thứ hai này cũng cung cấp cho bạn các giá trị và xử lý tương tự được lặp lại (bằng cách loại bỏ chúng).

Lần này Collectioncó thể là a Setthay vì a List(sự khác biệt là, Set không cho phép các giá trị lặp lại)

import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;

class Repeated {
      public static void main( String  [] args ) {

          Collection<String> listOne = Arrays.asList("milan","iga",
                                                    "dingo","iga",
                                                    "elpha","iga",
                                                    "hafil","iga",
                                                    "meat","iga", 
                                                    "neeta.peeta","iga");

          Collection<String> listTwo = Arrays.asList("hafil",
                                                     "iga",
                                                     "binga", 
                                                     "mike", 
                                                     "dingo","dingo","dingo");

          Collection<String> similar = new HashSet<String>( listOne );
          Collection<String> different = new HashSet<String>();
          different.addAll( listOne );
          different.addAll( listTwo );

          similar.retainAll( listTwo );
          different.removeAll( similar );

          System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
      }
}

Đầu ra:

$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]

Two:[hafil, iga, binga, mike, dingo, dingo, dingo]

Similar:[dingo, iga, hafil]

Different:[mike, binga, milan, meat, elpha, neeta.peeta]

Nếu nó không làm chính xác những gì bạn cần, nó sẽ mang lại cho bạn một khởi đầu tốt để bạn có thể xử lý từ đây.

Câu hỏi cho người đọc: Bạn sẽ bao gồm tất cả các giá trị lặp lại như thế nào?


@Oscar, Suy nghĩ chính xác của tôi, nhưng tôi không chắc liệu chúng tôi có thể sửa đổi nội dung của hay không listOne, nhưng dù sao thì +1!
Anthony Forloney

@poygenelubricants Ý bạn là gì khi loại raw không phải generic? Tại sao không?
OscarRyz

Oscar, bạn có thấy câu hỏi cập nhật của tôi không? Nó có hỗ trợ các giá trị lặp lại không?
user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "Việc sử dụng các kiểu thô trong mã được viết sau khi giới thiệu tính chung chung vào ngôn ngữ lập trình Java không được khuyến khích. Có thể các phiên bản trong tương lai của ngôn ngữ lập trình Java sẽ không cho phép sử dụng các kiểu thô. "
polygenelubricants

2
Câu trả lời @polygenelubricants được cập nhật để xử lý các bản sao và loại thô. BTW, phiên bản .. cao cấp của Java ... sẽ không bao giờ xảy ra. ;)
OscarRyz

37

Bạn có thể thử intersection()subtract()các phương pháp từ CollectionUtils.

intersection()method cung cấp cho bạn một tập hợp chứa các phần tử phổ biến và subtract()phương thức cung cấp cho bạn tất cả các phần tử không phổ biến.

Họ cũng nên quan tâm đến các yếu tố tương tự


5
Cần lưu ý rằng giải pháp này yêu cầu Apache Ccommons
Sir Codesalot,

9

Đây thực sự là những danh sách (có thứ tự, có trùng lặp) hay chúng là tập hợp (không có thứ tự, không có bản sao)?

Bởi vì nếu đó là cái sau, thì bạn có thể sử dụng, nói, a java.util.HashSet<E>và làm điều này trong thời gian tuyến tính dự kiến ​​bằng cách sử dụng tiện lợi retainAll.

    List<String> list1 = Arrays.asList(
        "milan", "milan", "iga", "dingo", "milan"
    );
    List<String> list2 = Arrays.asList(
        "hafil", "milan", "dingo", "meat"
    );

    // intersection as set
    Set<String> intersect = new HashSet<String>(list1);
    intersect.retainAll(list2);
    System.out.println(intersect.size()); // prints "2"
    System.out.println(intersect); // prints "[milan, dingo]"

    // intersection/union as list
    List<String> intersectList = new ArrayList<String>();
    intersectList.addAll(list1);
    intersectList.addAll(list2);
    intersectList.retainAll(intersect);
    System.out.println(intersectList);
    // prints "[milan, milan, dingo, milan, milan, dingo]"

    // original lists are structurally unmodified
    System.out.println(list1); // prints "[milan, milan, iga, dingo, milan]"
    System.out.println(list2); // prints "[hafil, milan, dingo, meat]"

Tôi thực sự không biết cấu trúc dữ liệu đó phải là. Nó có các bản sao. Bây giờ bạn có thể xem câu hỏi cập nhật
user238384

Nó có xóa các giá trị lặp lại khỏi tập dữ liệu không? coz Tôi không muốn mất bất kỳ giá trị nào :(
user238384

@agazerboy: Tôi đã cố gắng giải quyết cả hai câu hỏi. Vui lòng yêu cầu làm rõ hơn.
polygenelubricants

cảm ơn poly. Tôi đã thử chương trình của bạn với các bản sao, ví dụ như trong danh sách đầu tiên, tôi đã thêm "iga" hai lần nhưng nó vẫn trả về cho tôi câu trả lời là 3. Trong khi bây giờ nó phải là 4. coz list 1 có 4 giá trị tương tự. Nếu tôi thêm một mục nhiều lần, nó sẽ hoạt động. bạn nói gì? Cấu trúc dữ liệu nào khác?
user238384

6

Sử dụng java 8 removeIf

public int getSimilarItems(){
    List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
    List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
    int initial = two.size();

    two.removeIf(one::contains);
    return initial - two.size();
}

Có vẻ tốt, nhưng nếu tôi muốn giữ danh sách không bị sửa đổi, tôi sẽ phải sao chép một trong các danh sách và điều đó sẽ không được mong muốn trong một số trường hợp nhất định.
Sebastian D'Agostino

6

Nếu bạn đang tìm kiếm một cách tiện dụng để kiểm tra sự bằng nhau của hai tập hợp, bạn có thể sử dụng org.apache.commons.collections.CollectionUtils.isEqualCollection, so sánh hai tập hợp bất kể thứ tự.


4

Trong tất cả các cách tiếp cận, tôi thấy sử dụng org.apache.commons.collections.CollectionUtils#isEqualCollectionlà cách tiếp cận tốt nhất. Đây là những lý do -

  • Tôi không phải khai báo bất kỳ danh sách bổ sung / tự đặt mình
  • Tôi không thay đổi danh sách đầu vào
  • Nó rất hiệu quả. Nó kiểm tra sự bình đẳng trong độ phức tạp O (N).

Nếu không thể có apache.commons.collectionsphần phụ thuộc, tôi khuyên bạn nên triển khai thuật toán theo sau để kiểm tra tính bình đẳng của danh sách vì tính hiệu quả của nó.


3

Giải pháp đơn giản: -

    List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "d", "c"));
    List<String> list2 = new ArrayList<String>(Arrays.asList("b", "f", "c"));

    list.retainAll(list2);
    list2.removeAll(list);
    System.out.println("similiar " + list);
    System.out.println("different " + list2);

Đầu ra: -

similiar [b, c]
different [f]

1

Giả định hash1hash2

List< String > sames = whatever
List< String > diffs = whatever

int count = 0;
for( String key : hash1.keySet() )
{
   if( hash2.containsKey( key ) ) 
   {
      sames.add( key );
   }
   else
   {
      diffs.add( key );
   }
}

//sames.size() contains the number of similar elements.

Anh ta muốn danh sách các khóa giống hệt nhau, không phải có bao nhiêu khóa giống nhau. Tôi nghĩ.
Rosdi Kasim

Cảm ơn stefan đã giúp đỡ của bạn. Vâng, Rosdi đúng và bạn cũng vậy. Tôi cần tổng số các giá trị tương tự và cả các giá trị tương tự.
user238384

1

Tôi đã tìm thấy một ví dụ rất cơ bản về so sánh Danh sách tại So sánh Danh sách Ví dụ này xác minh kích thước trước tiên và sau đó kiểm tra tính khả dụng của phần tử cụ thể của một danh sách trong danh sách khác.


-1
public static boolean compareList(List ls1, List ls2){
    return ls1.containsAll(ls2) && ls1.size() == ls2.size() ? true :false;
     }

public static void main(String[] args) {

    ArrayList<String> one = new ArrayList<String>();
    one.add("one");
    one.add("two");
    one.add("six");

    ArrayList<String> two = new ArrayList<String>();
    two.add("one");
    two.add("six");
    two.add("two");

    System.out.println("Output1 :: " + compareList(one, two));

    two.add("ten");

    System.out.println("Output2 :: " + compareList(one, two));
  }

1
Giải pháp này trả về kết quả sai khi hai chứa 3 bản sao của "một". Nó không chính xác sẽ tạo ra một kết quả đúng.
Joseph Fitzgerald

Cảm ơn cho phần này: && ls1.size () == ls2.size ()
Nouar

1
Bất kỳ lý do nào mà bạn nghĩ ? true :falselà cần thiết cho đoạn mã của mình?
Krzysztof Tomaszewski
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.