2012-09-05 32 views
7

Tôi đang tìm cách giải quyết vấn đề sau:
Bắt đầu với bộ sưu tập A, tôi muốn chuyển một số loại 'xem' trên bộ sưu tập đó (nói bộ sưu tập B) sang một phương pháp nhất định. Khung nhìn B không cần chứa tất cả các phần tử của bộ sưu tập gốc A. Nếu trong đối tượng phương thức này được thêm vào hoặc bị loại bỏ khỏi khung nhìn (bộ sưu tập B), những thay đổi này cũng phải được phản ánh trên bộ sưu tập gốc A.Chế độ xem có thể sửa đổi Java trên bộ sưu tập

Ví dụ (pseudo-code): tình hình

  1. bắt đầu:

    Collection A = {1, 2, 3}; 
    View-on-collection B = {1, 2}; 
    
  2. Cách gọi:

    someMethod(B) { 
        B.add(4); 
        B.remove(2); 
    } 
    
  3. End tình hình:

    Collection A = {1, 3, 4}; 
    

Có ai biết giải pháp gọn gàng cho vấn đề này không?

+1

gì nếu bạn làm 'B.remove (3);' cho '3' là chỉ trong A? –

+0

Tôi đã nói 'subList', nhưng điều đó không hoàn toàn làm những gì bạn muốn (xem có vẻ như không bao giờ thay đổi kích thước, ngay cả khi bạn thêm những thứ vào nó). –

+1

@JoachimSauer: Chế độ xem có thể thay đổi kích thước bằng 'subList()'. – Keppil

Trả lời

-2

Bạn luôn có thể có hai bộ sưu tập khác nhau, một bộ sưu tập A và một bộ sưu tập B.

Sau đó, bất cứ khi nào bạn thêm một cái gì đó để B, bạn sẽ thêm nó vào A, và bất cứ khi nào lấy ra một cái gì đó từ B bạn cũng sẽ loại bỏ nó từ A.

Khi xóa khỏi A bạn sẽ kiểm tra xem có hay không B chứa đối tượng cần xóa và nếu có, bạn sẽ xóa đối tượng đó.

Tuy nhiên, khi thêm vào A, bạn sẽ không chạm vào B.

này có thể ít không gian hiệu quả hơn là một giải pháp tối ưu, nhưng nó sẽ không thay đổi thời gian phức tạp (ngoại trừ có lẽ xóa nội dung khỏi A.)

+0

Tại sao tôi có hai downvotes? Câu trả lời của tôi hoạt động tốt. – eboix

+1

Tôi đã không downvote nó, nhưng tôi nghĩ rằng nó không trả lời câu hỏi. Sử dụng hai bộ sưu tập không liên quan không phải là chế độ xem. Điểm có thể là hai bộ sưu tập sẽ được sử dụng trong các phần hoàn toàn khác nhau của mã, do đó không thể đồng bộ hóa thủ công. – lbalazscs

+0

@ lbalazscs Nhưng vấn đề là bạn tạo một Bộ sưu tập mới, bên trong, hoạt động như thế này. Tôi không đề xuất đồng bộ thủ công. Tôi chỉ nói rằng trong phương pháp thêm/loại bỏ phương pháp bạn làm những gì tôi đã nói trong câu trả lời của tôi. – eboix

0

Jacarta bộ sưu tập khuôn khổ có chức năng như vậy. Nhưng khuôn khổ này không hỗ trợ Generics. Hãy xem trên Google ổi. Tôi tin rằng họ cũng nên hỗ trợ chức năng như vậy.

4

Một cách là sử dụng List.sublist():

public static void main(String[] args) { 
    List<Integer> aList = new ArrayList<Integer>(Arrays.asList(1,2,3)); 
    List<Integer> view = aList.subList(0, 2); 

    view.add(new Integer(4)); 
    view.remove(new Integer(2)); 
    System.out.println("aList: " + aList); 
    System.out.println("view : " + view);   
} 

Một cách tổng quát hơn sẽ được thông qua ổi Collections2.filter(), cho phép bạn xác định một vị để kiểm soát các đối tượng nên trong giao diện:

public static void main(String[] args) { 

    List<Integer> aList = new ArrayList<Integer>(Arrays.asList(1,2,3)); 
    @SuppressWarnings("unchecked") 
    Collection<Integer> view = Collections2.filter(aList, new Predicate() { 
     public boolean apply(Object arg0) { 
      return ((Integer) arg0).intValue() % 3 != 0; 
     }}); 
    view.add(new Integer(4)); 
    view.remove(new Integer(2)); 
    System.out.println("aList: " + aList); 
    System.out.println("view : " + view); 

} 

Cả hai ví dụ đều in

aList: [1, 4, 3] 
view : [1, 4] 
+0

@Downvoter: Chăm sóc để giải thích? – Keppil

+1

Vâng, tôi cũng tìm thấy một cái gì đó như thế, nhưng vấn đề là danh sách con không đủ linh hoạt đối với chúng tôi: chúng tôi có thể muốn giữ lại một số yếu tố ở những vị trí ngẫu nhiên trong danh sách gốc, ví dụ: ở vị trí thứ nhất và thứ ba - tôi nghĩ chúng ta không đạt được điều đó bằng cách sử dụng subList. – Ward

+0

để làm cho mọi thứ rõ ràng, tôi không phải là kẻ phá hủy. – Ward

0

Bạn có thể mở rộng AbstractList (hoặc loại trừu tượng của bộ sưu tập bạn đang sử dụng)

Trong trừu tượng này, bạn có thể lấy bộ sưu tập nguồn trong hàm khởi tạo và giữ tham chiếu đến nó và điểm bắt đầu và kết thúc của khung nhìn danh sách gốc

Ghi đè các phương thức thêm/xóa/đặt để những hành động đó cũng được thực hiện trên bộ sưu tập nguồn.

ví dụ:

class ListView<T> extends AbstractList<T> { 

    int start = 0; 
    int end = 0; 
    private Collection<T> original = null; 

    public ListView(List<T> original, int start, int end) { 
     this.original = original; 
     this.start = start; 
     this.end = end; 
     super.addAll(0, original.subList(start, end)); 
    } 

    // Any add/set/remove must also alter the original 

}

Các ListView có hiệu quả phải là một Proxy vào danh sách gốc.

Ngoài ra, và với công việc nhiều hơn một chút, bạn có thể thực hiện bộ sưu tập hoặc Danh sách giao diện để bạn làm việc trực tiếp trên danh sách ban đầu trong một thời trang tương tự

Sau đó bạn có thể gọi phương thức của bạn hoặc vượt qua các ListView xung quanh như bạn sẽ là một bộ sưu tập bình thường.

ví dụ:

public void doSomeWork(Collection<String> collection); 

... 

object.doSomeWork(new ListView<String>(original, 0, 2)); 
+1

Tại sao điều này lại bị giảm giá, đó là một giải pháp hiệu quả và minh bạch cho vấn đề? –

+0

Tương tự ở đây. Tôi cũng đã bị bỏ phiếu. Ai đó có lẽ đã đăng một câu trả lời mới, nhìn thấy tất cả những câu trả lời khác, và muốn câu trả lời của anh ấy nằm trên đỉnh ...... – eboix

Các vấn đề liên quan