2016-08-01 8 views
63

Pierwotnie napisałem numer ArrayList i zapisałem w nim unikalne wartości (nazwy użytkowników, tj. Strings). Później musiałem użyć ArrayList, aby wyszukać, czy istnieje w nim użytkownik. To jest O(n) dla wyszukiwania.Czy warto przechowywać dane jako klucze w HashMap przy pustych/pustych wartościach?

Mój szef techniczny chciał, żebym to zmienił na HashMap i zapisał nazwy użytkowników jako klucze w tablicy, a wartości jako puste Strings.

Więc w Javie -

hashmap.put("johndoe",""); 

mogę sprawdzić, czy użytkownik istnieje później uruchamiając -

hashmap.containsKey("johndoe"); 

To O(1) prawda?

Mój szef powiedział, że był to skuteczniejszy sposób na zrobienie tego i miał dla mnie sens, ale wydawało się, że jest trochę za późno, aby umieścić puste/puste wartości w hashmap i przechowywać w nim elementy jako klucze.

Moje pytanie brzmi, czy to dobre podejście? Efektywność bije na poziomie ArrayList#contains lub ogólnie w poszukiwaniu tablic. To działa. Martwię się, nie widziałem, żeby ktokolwiek inny zrobił to po wyszukiwaniu. Być może brakuje mi jakiegoś oczywistego problemu, ale nie widzę go.

+2

plus1, ponieważ jest to prawidłowe pytanie, gdy nie znamy struktur danych Javy. – Daniel

+4

'HashSet' jest implementacją' HashMap.keySet() '. Jeśli chcesz zmienić mapę w zestaw, możesz użyć 'set = Collections.newSetFromMap (map)' –

+0

To pytanie nie jest błędne. To forum jest niewłaściwe. "Stack Overflow to strona z pytaniami i odpowiedziami dla programistów profesjonalnych i entuzjastów". – rdllopes

Odpowiedz

100

Ponieważ masz zestaw unikatowych wartości, odpowiednią strukturą danych jest Set. Możesz umieścić swoje wartości wewnątrz HashSet, implementacji interfejsu Set.

Moja ołowiu stwierdzono, że był bardziej skuteczny sposób to zrobić i to dla mnie sens, ale to po prostu wydawało się trochę off umieścić/null pusty jako wartości w HashMap i przechowywać elementy w nim jako kluczy.

Porada potencjalnego klienta jest wadliwa. Map nie jest odpowiednią abstrakcją do tego, Set jest. A Map jest odpowiedni dla par klucz-wartość. Ale nie masz wartości, tylko klucze.

Przykład użycia:

Set<String> users = new HashSet<>(Arrays.asList("Alice", "Bob")); 

System.out.println(users.contains("Alice")); 
// -> prints true 

System.out.println(users.contains("Jack")); 
// -> prints false 

Korzystanie z Map byłoby niewygodne, ponieważ to, co powinno być typ wartości? To pytanie nie ma sensu w twoim przypadku użycia, , ponieważ masz tylko klucze, a nie pary klucz-wartość. Dzięki Set nie musisz tego pytać, użycie jest całkowicie naturalne.

To jest O (1) prawda?

tak, szukając w HashMap lub HashSet O (1) zamortyzowane najgorszego przypadku, a wyszukiwanie w List lub tablicę O (n) w najgorszym przypadku.


Niektóre komentarze wskazują, że HashSet realizowany jest pod względem HashMap. To dobrze, na tym poziomie abstrakcji. Na poziomie abstrakcji wykonywanego zadania --- do przechowywania kolekcji unikalnych nazw użytkowników, użycie zestawu jest naturalnym wyborem, bardziej naturalnym niż mapa.

+2

Jedna rzecz, o której chciałbym wspomnieć, podczas gdy zgadzam się z tą odpowiedzią, powinieneś wyjaśnić ze swoim tech-leadem, czy był powód, dla którego potrzebna jest "mapa". Być może są oni przy założeniu, że używałbyś tej mapy do przechowywania innych informacji związanych z identyfikatorem użytkownika? Jeśli istnieje jakikolwiek inny powód, aby mieć dane związane z użytkownikiem w pamięci, prawdopodobnie chciałbyś go tam przechowywać zamiast tworzyć inną kolekcję gdzie indziej, powielając kod. – gmiley

+13

Należy zauważyć, że HashSet jest zaimplementowany jako HashMap z pustym obiektem (pojedynczą instancją dla wszystkich wartości) jako wartością. –

+0

@ JörgWMittag punkt targów, zaktualizowany, dzięki – janos

35

Jest to zasadniczo sposób implementacji HashSet, więc można powiedzieć, że to dobre podejście. Równie dobrze możesz użyć HashSet zamiast swoich HashMap z pustymi wartościami.

Na przykład

HashSet „S realizacja add jest

public boolean add(E e) { 
    return map.put(e, PRESENT)==null; 
} 

gdzie map jest podkład HashMap i PRESENT jest wartością obojętne.

Martwię się, nie widziałem, żeby ktokolwiek inny zrobił to po przeszukaniu. Być może brakuje mi jakiegoś oczywistego problemu, ale nie widzę go.

Jak już wspomniałem, twórcy JDK stosują to samo podejście.

+0

Dzięki, dlaczego nie wystarczy użyć istniejącej implementacji HashMap.put ("aaa" , "") zamiast HashSet? Również dlatego, że to podejście jest dobre, czy nie powoduje, że tablica jest nadmiarowa? – dozer

+21

@dozer HashSet jest już istniejącą klasą, która jest częścią JDK, więc po co odnawiać koło? Nie powoduje, że tablice są zbyteczne, ponieważ tablice są bardziej wydajne, gdy liczba elementów jest stała, a tablice (jak również ArrayLists) umożliwiają duplikaty. – Eran

+0

@dozer Nie ma za co – Eran

Powiązane problemy