Ze względu na kompletność ...
Powiedz, że naprawdę chcesz traktować Map
wartości jako List
s, ale chcesz uniknąć kopiowania Set
do za List
każdym razem.
Na przykład, może wywołujesz jedną funkcję biblioteczną, która tworzy Set
, ale przekazujesz swój Map<String, List<String>>
wynik do (słabo zaprojektowanej, ale wymykającej się z ręki) funkcji bibliotecznej, która bierze tylko Map<String, List<String>>
, chociaż jakoś wiesz, że operacje, które wykonuje z List
s mają jednakowe zastosowanie do dowolnych Collection
(a zatem dowolnych Set
). I z jakiegoś powodu musisz unikać narzutu / pamięci związanego z kopiowaniem każdego zestawu do listy.
W tym bardzo niszowym przypadku, w zależności od (być może niepoznawalnego) zachowania funkcji biblioteki List
wymaganej od ciebie , możesz być w stanie stworzyć List
widok każdego zestawu. Zauważ, że jest to z natury niebezpieczne (ponieważ wymagania funkcji bibliotecznych dla każdej z nich List
mogą prawdopodobnie ulec zmianie bez twojej wiedzy), dlatego należy preferować inne rozwiązanie. Ale oto jak to zrobisz.
Utworzyłbyś klasę, która implementuje List
interfejs, bierze Set
konstruktora i przypisuje ten zestaw do pola, a następnie używa tego wewnętrznego Set
do implementacji List
interfejsu API (w możliwym zakresie i pożądanym).
Zwróć uwagę, że niektóre zachowania List po prostu nie będą w stanie naśladować bez przechowywania elementów jako a List
, a niektóre zachowania będą tylko częściowo możliwe do naśladowania. Ponownie, ta klasa nie jest List
ogólnie bezpiecznym zamiennikiem dla s. W szczególności, jeśli wiesz, że przypadek użycia wymaga operacji związanych z indeksem lub MUTOWANIA List
, to podejście pójdzie bardzo szybko na południe.
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);
...