Path: csiph.com!usenet.pasdenom.info!weretis.net!feeder4.news.weretis.net!eternal-september.org!feeder.eternal-september.org!mx04.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: optimsed HashMap Date: Tue, 27 Nov 2012 08:56:07 -0500 Organization: A noiseless patient Spider Lines: 50 Message-ID: References: <8i70b8d0pm6ibk03ti4t2pv60jd0bctlcs@4ax.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Tue, 27 Nov 2012 13:56:14 +0000 (UTC) Injection-Info: mx04.eternal-september.org; posting-host="ffb8f7085759b339c1002252b48331a4"; logging-data="2385"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Do5dIeEosR5YNG0ptH1jH" User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:17.0) Gecko/17.0 Thunderbird/17.0 In-Reply-To: Cancel-Lock: sha1:sWqlpxaVL94uB6yVM6MswRHYWY4= Xref: csiph.com comp.lang.java.programmer:19996 On 11/27/2012 5:01 AM, Arved Sandstrom wrote: > On 11/26/2012 09:28 PM, Eric Sosman wrote: >> On 11/26/2012 6:44 PM, Daniel Pitts wrote: >>> >>> I don't think your use-case needs this kind of (read "micro") >>> optimization. However, I have often wished for a way to get a Map.Entry >>> for a key, which could then be used to insert a new value efficiently. >>> >>> Map.Entry getOrAddEntry(K key); >>> >>> Map.Entry e = map.getOrAddEntry(myKey); >>> if (e.getValue() == null) { >>> e.setValue(newValue(myKey)); >>> } >>> useValue(e.getValue()); >>> >>> Alas, not exactly possible to add it now. >> >> java.util.concurrent.ConcurrentMap has putIfAbsent(). >> > It's almost certainly a reflection (no pun intended) of what I do with > Maps, but a common variant use case for me is > > putEmptyListAndAddValueToListIfAbsent > > I don't normally use ConcurrentHashMap so the usual idiom for me is a > contains() check that may put() the new empty list as a value, > afterwards the list (empty or otherwise) is always got, and the actual > value added to it. I usually write it as List list = map.get(key); if (list == null) { list = new SomeKindOfList(); map.put(key, list); } list.add(newValue); ... which involves one extra lookup per mapped key, not one extra lookup per query. The imaginary getOrAddEntry() would be nice, although it might complicate the Map.Entry interface itself (you'd want a way to distinguish "This key maps to null" from "This key is newly entered"). -- Eric Sosman esosman@comcast-dot-net.invalid