Demi kelengkapan ...
Katakan bahwa Anda benar - benar ingin memperlakukan Map
nilai sebagai List
s, tetapi Anda ingin menghindari menyalin Set
ke dalam List
setiap waktu.
Misalnya, mungkin Anda memanggil satu fungsi pustaka yang menciptakan Set
, tetapi Anda meneruskan Map<String, List<String>>
hasil Anda ke fungsi pustaka (yang dirancang dengan buruk tetapi tidak ada di tangan Anda) yang hanya membutuhkan waktu Map<String, List<String>>
, meskipun entah bagaimana Anda tahu bahwa operasi itu dilakukan dengan List
s sama-sama berlaku untuk semua Collection
(dan dengan demikian ada Set
). Dan untuk beberapa alasan Anda perlu menghindari kecepatan / memori overhead menyalin setiap Set ke Daftar.
Dalam kasus ceruk super ini, tergantung pada perilaku (mungkin tidak diketahui) fungsi perpustakaan perlu dari Anda List
, Anda mungkin dapat membuat List
tampilan atas setiap Set. Perhatikan bahwa ini pada dasarnya tidak aman (karena persyaratan fungsi pustaka dari masing List
- masing mungkin bisa berubah tanpa Anda sadari), jadi solusi lain harus lebih disukai. Tapi begini caranya.
Anda akan membuat kelas yang mengimplementasikan List
antarmuka, mengambil Set
dalam konstruktor dan menetapkan bahwa Set ke bidang, dan kemudian menggunakan internal itu Set
untuk mengimplementasikan List
API (sejauh mungkin, dan diinginkan).
Perhatikan bahwa beberapa perilaku Daftar yang tidak dapat Anda tiru tanpa menyimpan elemen sebagai List
, dan beberapa perilaku yang hanya sebagian Anda dapat tiru. Sekali lagi, kelas ini bukan pengganti drop-in yang aman untuk List
s secara umum. Secara khusus, jika Anda tahu bahwa use case membutuhkan operasi terkait indeks atau MUTATING List
, pendekatan ini akan berjalan sangat cepat ke selatan.
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);
...