2015-07-23 20 views
10

Urządzenie Collections.singleton() method zwraca Set z tym pojedynczym argumentem zamiast z Collection.Jaki jest pożytek z Collections.singleton(), aby zwrócić zestaw zamiast kolekcji?

Dlaczego tak jest? Z tego, co widzę, poza Set będącym podtypem Collection, nie widzę żadnej przewagi ... Czy to tylko dlatego, że Set przedłuża Collection tak więc nie ma powodu, aby tego nie robić?

I tak, istnieje również Collections.singletonList() ale to jest inna sprawa, ponieważ można uzyskać dostęp losowych elementów z List z .get() ...

+2

Jedyną zaletą mogę myśleć byłoby to, że metody, które akceptują 'Set' nie zaakceptuje' Collections.singleton() 'gdyby wrócił prosty' Collection'. –

+0

@Slanec rzeczywiście ...Podczas gdy metody przyjmujące "Kolekcję" chętnie przyjmą również "Zestaw" ... – fge

+0

Być może dlatego, że słowo "singleton" w matematyce oznacza zbiór. – immibis

Odpowiedz

7

nie jestem pewien, że to jest „korzyścią” lub „przewagę” per se ? Jest to po prostu metoda, która zwraca singleton Set i jest domyślną implementacją, gdy chcesz singleton Collection, ponieważ singleton Collection jest również zestawem matematycznym.

+5

Tak naprawdę nie poszedłem tak głęboko jak matematyczne określenie zestawu, ale tak, to prawda. W rzeczywistości korzyść naprawdę wydaje się, że skoro w tym konkretnym przypadku "Collection" i "Set" są w zasadzie równoważne, dlaczego nie zwrócić 'Set'? W końcu gdyby istniała jakaś różnica, prawdopodobnie mielibyśmy '.singletonCollection()' oraz '.singletonSet()' ... – fge

-1

Nie wszystkie listy są losowe, wystarczy wziąć LinkedList (dostęp losowy w API, a nie w implementacji) jako kontrprzykład. Przy okazji zgadzam się z Louisem Wassermanem, Set ma po prostu sens, ponieważ jest bliższy matematycznej definicji, po prostu wydaje się naturalny.

+0

Przepraszam, ale umowa 'List' wymaga, abyś mógł' .get() 'z dowolny indeks. Niezależnie od tego, co sugeruje duża O, ale jest to wymóg. A to w zasadzie przypadkowy dostęp do elementów. – fge

+0

'ArrayList' implementuje' RandomAccess', 'LinkedList' nie. Zobacz Javadoc. Przypadkowy dostęp niejawnie oznacza, że ​​koszt takiego wyszukiwania jest niski, a najczęściej stały. Javadoc z 'RandomAccess' wyraźnie wspomina o charakterystyce wydajnościowej w celu ustalenia, czy lista powinna być oznaczona jako dostęp losowy, czy nie – Dici

+0

I _know_ o interfejsie' RandomAccess'. Faktem jest, że 'List' zapewnia' .get (xx) 'gdzie' xx' jest indeksem na liście - niezależnie od tego, czy ta konkretna implementacja implementuje 'RandomAccess'! – fge

1

Zastanawiałem się nad tym samym i natknąłem się na twoje pytanie w moich badaniach. Oto mój wniosek:

Zwrócenie numeru Set powoduje, że interfejs API kolekcji jest czysty.

Oto sposoby uzyskiwania singleton Kolekcja:

  • public static <T> Set<T> singleton(T o)
  • public static <T> List<T> singletonList(T o)
  • public static <K,V> Map<K,V> singletonMap(K key, V value)

Co jeśli projektanci API zdecydowały o konieczności metodę singletonSet metoda i singleton ? to będzie wyglądać następująco:

  • public static <T> Collection<T> singleton(T o)
  • public static <T> Set<T> singletonSet(T o)
  • public static <T> List<T> singletonList(T o)
  • public static <K,V> Map<K,V> singletonMap(K key, V value)

Czy metoda singleton naprawdę konieczne? Zastanówmy się, dlaczego potrzebowalibyśmy niektórych z tych metod.

Zastanów się, kiedy zadzwonisz pod numer singletonList? Prawdopodobnie masz interfejs API wymagający List zamiast Collection lub Set. Użyję tego biednego przykład:

public void needsList(List<?> list); 

można jedynie zdać List. needsList Mam nadzieję, że potrzebuje danych zindeksowanych i nie żąda arbitralnie List zamiast Collection.

Jednak można również przekazać List do metody, która wymaga każdy Collection:

public void needsAnyCollection(Collection<?> collection); 

Ale jeśli tak jest, to dlaczego używać List? A List ma bardziej skomplikowany interfejs API i obejmuje przechowywanie indeksów. Czy naprawdę potrzebujesz indeksów? Czy nie wystarczyłoby Set? Twierdzę, że powinieneś użyć Set, ponieważ needsAnyCollection nie dba o zamówienie.

To tutaj naprawdę świeci singletonSet. Wiesz, że jeśli kolekcja ma rozmiar 1 (singleton), dane muszą być unikalne. Kolekcje wielkości 1 są przypadkowo zbiorem.

Nie ma potrzeby stosowania metody, która zwraca singleton typu Collection, ponieważ jest to przypadkowo Set.

2

Niezmienne

Korzyść znajduje się w pierwszej przymiotnik czytać w that JavaDoc documentation: niezmienne.

Są chwile, kiedy pracujesz z kodem, który wymaga Set (lub List, itp.). W twoim własnym kontekście możesz mieć ścisłą potrzebę tylko jednego przedmiotu. Aby zrealizować własny cel, jakim jest wymuszenie reguły pojedynczego elementu tylko podczas prezentacji tego elementu w zestawie, należy użyć implementacji Set, która zabrania dodawania więcej niż jednego elementu.

"Niezmienny" na Collections::singleton oznacza, że ​​po utworzeniu wynikowy obiekt Set ma jedną i tylko jedną pozycję. Nie zero i nie więcej niż jeden. Nie można dodać więcej. Jeden przedmiot nie może zostać usunięty.

Na przykład wyobraź sobie, że Twój kod współpracuje z obiektem Employee reprezentującym CEO (Chief Executive Officer) Twojej firmy. Twój kod jest jawnie dotyczy tylko CEO, więc wiesz, że może istnieć tylko jeden taki obiekt na raz, zawsze dokładnie jeden CEO. Mimo to chcesz wykorzystać istniejący kod, który tworzy raport dla określonego zbioru obiektów: Employee. Korzystając z usługi Collection.singleton masz gwarancję, że Twój własny kod nie będzie miał błędnie innego niż pojedynczy pracownik, a mimo to będzie mógł przekazać numer Set.

Set<Employee> ceo = Collections.singleton(new Employee("Tim Cook")) ; // Always exactly one item in this context, only one CEO is possible. 

ceo.add(…) ;  // Fails, as the collection is immutable. 
ceo.clear() ;  // Fails, as the collection is immutable. 
ceo.remove(…) ; // Fails, as the collection is immutable. 

someReport.processEmployees(ceo) ; 

Java 9: ​​Set.of & List.of

Java 9 i później oferuje nowe metody interfejsu Set.of i List.of do th sam efekt, co stanowi niezmienny zbiór pojedynczego elementu.

Set<Pet> pet = Set.of(someDog) ; 

Ale rodzeństwo of metody są przeciążone przyjąć dowolną liczbę elementów się w zbiorach niezmiennego, a nie tylko jeden element.

Set<Pet> pets = Set.of(someDog , someOtherDog , someCat) ;