Załóżmy, że mamy HashMap<String, Integer>
Javę.
Jak zaktualizować (zwiększyć) wartość całkowitą klucza ciągu dla każdego istnienia znalezionego ciągu?
Można usunąć i ponownie wprowadzić parę, ale narzut byłby problemem.
Innym sposobem byłoby po prostu umieszczenie nowej pary, a stara zostanie zastąpiona.
W tym drugim przypadku, co się stanie, jeśli dojdzie do zderzenia kodu skrótu z nowym kluczem, który próbuję wstawić? Prawidłowe zachowanie tablicy mieszającej oznaczałoby przypisanie jej innego miejsca lub utworzenie z niej listy w bieżącym segmencie.
getOrDefault
na przykład:map.put(key, count.getOrDefault(key, 0) + 1);
Java 8 sposób:
Możesz użyć
computeIfPresent
metody i podać jej funkcję mapowania, która zostanie wywołana w celu obliczenia nowej wartości na podstawie istniejącej.Na przykład,
Alternatywnie można użyć
merge
metody, gdzie 1 jest wartością domyślną, a funkcja zwiększa istniejącą wartość o 1:Dodatkowo, istnieje kilka innych przydatnych metod, takich jak
putIfAbsent
,getOrDefault
,forEach
, etc.źródło
null
(powiedzmywords.put("hello", null);
), wynik wciążnull
nie jest taki,1
jak się spodziewałbym.compute()
zamiast tego, będzie również obsługiwaćnull
wartości..merge
to moje rozwiązanieInteger::sum
.Metoda
put
będzie zastąpić wartość istniejącego klucza i stworzy go, jeśli nie istnieje.źródło
nullPointer Exception
.null + 1
ponieważ spowoduje to rozpakowanienull
liczby całkowitej w celu wykonania przyrostu.Uproszczony sposób Java 8 :
Korzysta z metody HashMap, która pobiera wartość klucza, ale jeśli klucza nie można odzyskać, zwraca określoną wartość domyślną (w tym przypadku „0”).
Jest to obsługiwane w rdzeniu Java: HashMap <K, V> getOrDefault (Klucz obiektu, V defaultValue)
źródło
Zamień
Integer
naAtomicInteger
i wywołaj jedną z metodincrementAndGet
/getAndIncrement
.Alternatywą jest zawinięcie
int
we własnąMutableInteger
klasę, która maincrement()
metodę, do rozwiązania jest jeszcze tylko kwestia bezpieczeństwa wątków.źródło
MutableInteger
jest lepsze, jakAtomicInteger
zastosowaniavolatile
, które mają narzut. Użyłbymint[1]
zamiastMutableInteger
.Rozwiązanie jednoliniowe:
źródło
@ Rozwiązanie Matthew jest najprostsze i w większości przypadków będzie działać wystarczająco dobrze.
Jeśli potrzebujesz wysokiej wydajności, AtomicInteger jest lepszym rozwiązaniem ala @BalusC.
Jednak szybszym rozwiązaniem (pod warunkiem, że bezpieczeństwo wątków nie stanowi problemu) jest użycie TObjectIntHashMap, która zapewnia metodę przyrostu (klucza) i wykorzystuje operacje podstawowe i mniej obiektów niż tworzenie AtomicIntegers. na przykład
źródło
Możesz zwiększyć jak poniżej, ale musisz sprawdzić istnienie, aby wyjątek NullPointerException nie został zgłoszony
źródło
Czy istnieje skrót (z wartością 0), czy też jest on „wstawiany” do mapy przy pierwszym kroku? Jeśli zostanie „wstawiony” do pierwszego przyrostu, kod powinien wyglądać następująco:
źródło
Może być trochę późno, ale oto moje dwa centy.
Jeśli używasz Java 8, możesz skorzystać z metody computeIfPresent . Jeśli wartość określonego klucza jest obecna i ma wartość inną niż null, wówczas próbuje obliczyć nowe odwzorowanie, biorąc pod uwagę klucz i jego bieżącą wartość odwzorowaną.
Możemy również użyć innej metody putIfAbsent do wprowadzenia klucza. Jeśli określony klucz nie jest już powiązany z wartością (lub jest odwzorowany na wartość NULL), wówczas ta metoda wiąże go z podaną wartością i zwraca wartość NULL, w przeciwnym razie zwraca bieżącą wartość.
W przypadku, gdy mapa jest wspólna dla wątków następnie możemy wykorzystać
ConcurrentHashMap
i AtomicInteger . Z dokumentu:Możemy ich używać, jak pokazano:
Należy zauważyć, że wzywamy,
get
aby uzyskać wartość klucza,B
a następnie wywołujemyincrementAndGet()
jej wartość, co oczywiście jestAtomicInteger
. Możemy go zoptymalizować, ponieważ metodaputIfAbsent
zwraca wartość klucza, jeśli już istnieje:Na marginesie, jeśli planujemy użyć AtomicLong, to zgodnie z dokumentacją w wysokiej rywalizacji spodziewana przepustowość LongAdder jest znacznie wyższa, kosztem wyższego zużycia miejsca. Sprawdź także to pytanie .
źródło
Czystsze rozwiązanie bez NullPointerException to:
źródło
Ponieważ nie mogę skomentować kilku odpowiedzi z powodu mniejszej reputacji, opublikuję rozwiązanie, które zastosowałem.
źródło
Użyj
for
pętli, aby zwiększyć indeks:źródło
Istnieją mylące odpowiedzi na to pytanie, które sugerują, że metoda wprowadzania Hashtable zastąpi istniejącą wartość, jeśli klucz istnieje, nie dotyczy to Hashtable, ale raczej HashMap. Zobacz Javadoc dla HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29
źródło
lub
Liczba całkowita jest pierwotnymi typami danych http://cs.fit.edu/~ryan/java/language/java-data.html , więc musisz ją wyjąć, zrobić trochę procesu, a następnie odłożyć. jeśli masz wartość, która nie jest pierwotnym typem danych, wystarczy ją wyjąć, przetworzyć, nie trzeba ponownie umieszczać jej w haszapie.
źródło
Próbować:
UWAGA:
Możesz zmienić klucz lub wartość w haszapie, ale nie możesz zmienić obu jednocześnie.
źródło
Użyj wbudowanej funkcji Java8 „computeIfPresent”
Przykład:
źródło