Vì lợi ích của sự hoàn chỉnh ...
Nói rằng bạn thực sự muốn coi các Map
giá trị là List
s, nhưng bạn muốn tránh sao chép Set
vào List
mỗi lần.
Chẳng hạn, có thể bạn đang gọi một hàm thư viện tạo ra một Set
, nhưng bạn đang chuyển Map<String, List<String>>
kết quả của mình sang hàm thư viện (được thiết kế kém nhưng nằm ngoài tầm tay) chỉ thực hiện Map<String, List<String>>
, mặc dù bằng cách nào đó bạn biết rằng nó hoạt động với List
s được áp dụng như nhau cho bất kỳ Collection
(và do đó bất kỳ Set
). Và vì một số lý do, bạn cần tránh tốc độ / chi phí bộ nhớ khi sao chép từng Set thành Danh sách.
Trong trường hợp siêu thích hợp này, tùy thuộc vào hành vi (có thể không thể biết) mà chức năng thư viện cần từ bên ngoài của bạn List
, bạn có thể tạo List
chế độ xem qua mỗi Bộ. Lưu ý rằng điều này vốn không an toàn (vì các yêu cầu của chức năng thư viện List
có thể thay đổi mà bạn không biết), vì vậy nên sử dụng giải pháp khác. Nhưng đây là cách bạn làm điều đó.
Bạn sẽ tạo một lớp thực hiện List
giao diện, lấy một Set
hàm tạo và gán Set đó cho một trường, sau đó sử dụng nội bộ đó Set
để triển khai List
API (trong phạm vi có thể và mong muốn).
Lưu ý rằng một số hành vi Danh sách mà bạn đơn giản sẽ không thể bắt chước mà không lưu trữ các phần tử dưới dạng List
và một số hành vi bạn sẽ chỉ có thể bắt chước một phần. Một lần nữa, lớp này không phải là sự thay thế thả vào an toàn cho List
s nói chung. Đặc biệt, nếu bạn biết rằng ca sử dụng yêu cầu các hoạt động liên quan đến chỉ mục hoặc MUTATING List
, cách tiếp cận này sẽ đi về phía nam rất nhanh.
public class ListViewOfSet<U> implements List<U> {
private final Set<U> wrappedSet;
public ListViewOfSet(Set<U> setToWrap) { this.wrappedSet = setToWrap; }
@Override public int size() { return this.wrappedSet.size(); }
@Override public boolean isEmpty() { return this.wrappedSet.isEmpty(); }
@Override public boolean contains(Object o) { return this.wrappedSet.contains(o); }
@Override public java.util.Iterator<U> iterator() { return this.wrappedSet.iterator(); }
@Override public Object[] toArray() { return this.wrappedSet.toArray(); }
@Override public <T> T[] toArray(T[] ts) { return this.wrappedSet.toArray(ts); }
@Override public boolean add(U e) { return this.wrappedSet.add(e); }
@Override public boolean remove(Object o) { return this.wrappedSet.remove(o); }
@Override public boolean containsAll(Collection<?> clctn) { return this.wrappedSet.containsAll(clctn); }
@Override public boolean addAll(Collection<? extends U> clctn) { return this.wrappedSet.addAll(clctn); }
@Override public boolean addAll(int i, Collection<? extends U> clctn) { throw new UnsupportedOperationException(); }
@Override public boolean removeAll(Collection<?> clctn) { return this.wrappedSet.removeAll(clctn); }
@Override public boolean retainAll(Collection<?> clctn) { return this.wrappedSet.retainAll(clctn); }
@Override public void clear() { this.wrappedSet.clear(); }
@Override public U get(int i) { throw new UnsupportedOperationException(); }
@Override public U set(int i, U e) { throw new UnsupportedOperationException(); }
@Override public void add(int i, U e) { throw new UnsupportedOperationException(); }
@Override public U remove(int i) { throw new UnsupportedOperationException(); }
@Override public int indexOf(Object o) { throw new UnsupportedOperationException(); }
@Override public int lastIndexOf(Object o) { throw new UnsupportedOperationException(); }
@Override public ListIterator<U> listIterator() { throw new UnsupportedOperationException(); }
@Override public ListIterator<U> listIterator(int i) { throw new UnsupportedOperationException(); }
@Override public List<U> subList(int i, int i1) { throw new UnsupportedOperationException(); }
}
...
Set<String> set = getSet(...);
ListViewOfSet<String> listOfNames = new ListViewOfSet<>(set);
...