2013-02-08 35 views
5

Tôi đang gặp khó khăn để có được giao điểm của một số Danh sách trên Java. Những gì tôi đang làm điều này là: tôi nhận được (cho phép nói) 3 Danh sách các số nguyên:Nhận giao lộ của một số Danh sách bằng cách sử dụng retainAll trong Java

danh sách 1: [2, 2, 2, 2, 5, 5]

danh sách 2: [2 , 2, 103]

danh sách 3: [2, 431]

tôi đang làm đơn retainAll để là người đầu tiên sử dụng mỗi danh sách còn lại:

list1.retainAll(list2); 
list1.retainAll(list3); 

Và tôi nhận này kết quả:

list1: [2, 2, 2, 2]

Nhưng tôi mong đợi để có được điều này một:

list1: [2]

... Kể từ yếu tố duy nhất tất cả danh sách cổ phiếu là một 2 và không bốn 2.

tôi biết điều này có lẽ là hành vi mong đợi của hàm retainAll, nhưng tôi cần để có được những kết quả tôi đã đề cập ở trên.

Bất kỳ trợ giúp nào?

Chỉnh sửa: Sử dụng HashSet để không cho phép trùng lặp sẽ không thực hiện thủ thuật. Trong trường hợp này, ví dụ:

danh sách 1: [2, 2, 2, 2, 5, 5]

danh sách 2: [2, 2, 103]

danh sách 3: [2 , 2, 2, 431]

tôi cần để có được một kết quả của:

danh sách 1: [2, 2] (vì tất cả các danh sách có ít nhất một cặp 2 của)

Thay vì

danh sách 1: [2]

+0

Trước tiên, bạn cần nêu rõ những gì bạn mong đợi. Bạn có muốn giữ lại các giá trị giống nhau và ở cùng một chỉ mục trong cả hai danh sách không? Hoặc bạn có muốn giữ các phần tử có trong cả hai danh sách và chỉ giữ cùng một số như trong danh sách thứ hai? Hay cái gì khác? –

Trả lời

5

gì về phương pháp này:

public static <T> Collection <T> intersect (Collection <? extends T> a, Collection <? extends T> b) 
{ 
    Collection <T> result = new ArrayList <T>(); 

    for (T t: a) 
    { 
     if (b.remove (t)) result.add (t); 
    } 

    return result; 
} 

public static void main (String [] args) 
{ 
    List <Integer> list1 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 2, 2, 2, 5, 5)); 
    List <Integer> list2 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 2, 103)); 
    List <Integer> list3 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 431)); 

    System.out.println (intersect (list1, intersect (list2, list3))); 
} 
+1

Điều này thực hiện chính xác những gì tôi muốn. Nếu một cặp số xuất hiện trên mỗi mảng, nó sẽ được hiển thị dưới dạng hai số và không chỉ là một số. – Multitut

0

Thay vì danh sách bạn cần cấu trúc dữ liệu được gọi là túi hoặc nhiều bộ. Apache commons bộ sưu tập thư viện ví dụ bao gồm một:

http://commons.apache.org/collections/apidocs/org/apache/commons/collections/Bag.html#retainAll(java.util.Collection)

+1

Phương thức 'retainAll' được liên kết * không * tôn trọng cardinality, đó là những gì anh ta đang cố gắng hoàn thành. – ataylor

+0

Việc thực hiện trong túi commons không. * "Hành vi được chỉ định trong nhiều phương pháp này không giống như hành vi được chỉ định bởi Bộ sưu tập." * – Joni

+0

Ồ, bạn tham khảo đa số của Ổi. Tôi đang loại bỏ các tham chiếu đến nó sau đó. – Joni

0

Với retainAll bạn sẽ nhận được câu trả lời sai như bạn nói. Tôi khuyên bạn nên sử dụng HashMap giữ integer/count cặp và quét từng danh sách khác và thu hẹp map của bạn.

  1. Nhập số map từ các giá trị list1.
  2. Lặp lại trên mỗi danh sách khác và lấy min(# of intg in other_list, map.get(intg)) và cập nhật map với giá trị đó.
  3. Kết quả map sẽ là giao điểm của tất cả các danh sách.
2

Vấn đề này có thể được giải quyết dễ dàng hơn với một cấu trúc dữ liệu MultiSet. Ví dụ: nếu bạn sử dụng số Multiset của guava, bạn có thể sử dụng Multisets.retainOccurrences()

2

Tôi sẽ sử dụng một số loại Set, có thể là HashSet. Chúng sẽ không thêm các phần tử trùng lặp và chúng có phương thức retainAll.

Set<Integer> uniqueNums = new HashSet<Integer>(list1); 
uniqueNums.retainAll(list2); 
uniqueNums.retainAll(list3); 

Đây là javadocs cho Set.

+0

Xin cảm ơn, nhưng nó sẽ không thực hiện. -Tôi đã cập nhật câu hỏi. – Multitut

0

Đây là một thứ bạn thích và nó là đệ quy.

public static <T> List<T> intersect(List<T> c1, List<T> c2) { 
    List<T> inter = new ArrayList<>(c1); 
    inter.retainAll(c2); 
    return inter; 
} 

public static <T> List<T> intersect(List<T> first, List<T>... rest) { 
    if (rest.length == 0) 
     return first; 

    List<T> second = rest[0]; 

    first = intersect(first,second); 
    rest = Arrays.copyOfRange(rest, 1, rest.length); 

    return intersect(first, rest); 
} 
Các vấn đề liên quan