Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > HashMap get/put

Reply
Thread Tools

HashMap get/put

 
 
Lew
Guest
Posts: n/a
 
      10-30-2009
(attribution restored)
Lew wrote:
>> But you cannot expect the compiler to catch all your mistakes. So
>> this was one that it couldn't catch because in their infinite wisdom
>> the Powers That Be decreed that 'Map#get()' not be type
>> parameterized.


Mike Schilling wrote:
> Which we still don't have a good explanation for. The closest to a


What, "infinite wisdom" isn't a good enough explanation?

> real use case for get(Object) rather than get(K) we've seen is
> Patricia's, and that could be made to work with get(K) simply enough
> by letting K be List instead of ArrayList.


One of the beauties of the Java community is that the practitioners don't
blindly accept all the language's features with religious fervor, but question
and challenge pretty nearly all its decisions. This bodes well for the health
of the platform.

"No one pretends that Java is perfect or all-wise. Indeed, it has been said
that Java is the worst programming language except all those others that have
been tried from time to time."

(With apologies to Sir Winston Churchill)

--
Lew
 
Reply With Quote
 
 
 
 
Kevin McMurtrie
Guest
Posts: n/a
 
      10-30-2009
In article <hcb95q$mvt$>, Lew <>
wrote:

> Kevin McMurtrie wrote:
> > Generics is extremely helpful for common source code mistakes but it is
> > by no means a powerful tool. There have been many, many long threads
> > about it here.

>
> There may have been long threads about it, but generics most assuredly is a
> powerful tool. Perhaps you just haven't learned to use it correctly yet.


I think my expectations of a 'powerful tool' are greater than yours.
--
I won't see Goolge Groups replies because I must filter them as spam
 
Reply With Quote
 
 
 
 
Mike Schilling
Guest
Posts: n/a
 
      10-30-2009
Lew wrote:
> (attribution restored)
> Lew wrote:
>>> But you cannot expect the compiler to catch all your mistakes. So
>>> this was one that it couldn't catch because in their infinite
>>> wisdom
>>> the Powers That Be decreed that 'Map#get()' not be type
>>> parameterized.

>
> Mike Schilling wrote:
>> Which we still don't have a good explanation for. The closest to a

>
> What, "infinite wisdom" isn't a good enough explanation?


Call me picky.


 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      10-30-2009
Kevin McMurtrie wrote:
> In article <hcb95q$mvt$>, Lew <>
> wrote:
>
>> Kevin McMurtrie wrote:
>>> Generics is extremely helpful for common source code mistakes but it is
>>> by no means a powerful tool. There have been many, many long threads
>>> about it here.

>> There may have been long threads about it, but generics most assuredly is a
>> powerful tool. Perhaps you just haven't learned to use it correctly yet.

>
> I think my expectations of a 'powerful tool' are greater than yours.


I think it's question of how powerful, and that there are objective rationales
for calling generics powerful.

Generics permit one to lock down the type relationships in code and push
possible runtime exceptions into compiler messages. The industry rule of
thumb is that compile time fixes are ten times cheaper than run time fixes.
Ten to one is powerful.

Generics force one to thoroughly analyze the type relationships. They
directly express that analysis. Type analysis is very powerful and the
ability to express it commensurately so.

Documentation internal to code is powerful. It speeds understanding for
maintenance programmers and prevents their errors.

Generics increase the ability to refactor code safely. If a type parameter
for interface 'Blah' is '<T extends Collection <Foo> & Serializable>' one can
reify that as 'ArrayList' initially and refactor to 'HashSet' without pain.
One will not be able to accidentally substitute a non-serializable collection.
One will be able to extract 'Foo' elements safely.

Client code can ignore the details secure in those promises. Encapsulation is
powerful:

public interface Blah <T extends Collection <Foo> & Serializable>
{
T getItems();
}

Client:

Blah <?> blah = BlahImpl.make();
Collection <Foo> foos = blah.getItems();

Information hiding, type safety, easier and less risky refactoring, simpler
client code - taken together they show that generics are at least somewhat
powerful.

--
Lew
 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      10-30-2009
Wojtek wrote:

> Or rather, why does the spec not say get(K key) instead of get(Object o)


I'm not really sure why this is. Possibly the designers felt the same
way many in the news group do -- get(Object) is correct.

This doesn't really answer your question, but if you need (or feel you
will benefit from) a map with a parameterized get(K), then it's not
really hard to add one:

public interface MapWithGenericGet<K, V>
extends Map<K, V>
{
V getGeneric( K key );
}

class HashMapWithGenericGet<K, V>
extends HashMap<K, V>
implements MapWithGenericGet<K, V>
{
@Override
public V getGeneric( K key )
{
return get( key );
}
}


I don't know why the API designers didn't add such a thing. Maybe they
figured no one would really use it. But it's safe and easy enough to do
yourself. You just have to remember to use getGeneric() instead of
plain old get().


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      10-30-2009
Wojtek wrote:
> If I have the following:
>
> HashMap<MyKey,MyValue> map = new HashMap<MyKey,MyValue>();
> [...]
> Or rather, why does the spec not say get(K key) instead of get(Object o)


Map<Politician,Party> congress =
new HashMap<Politician,Party>();
congress.put(new Politician("Barney Frank", Party.DEMOCRATIC);
congress.put(new Politician("Dan Lungren", Party.REPUBLICAN);
...

// returns Party.DEMOCRATIC
Party p = congress.get(new Politician("Brad Ellsworth"));

// returns null
Party q = congress.get(new Politician("Dan Rostenkowski"));

Pretty straightforward: We've got a Map that gives us the party
affiliation of any member of Congress, or that returns null if we
ask about someone who's not in Congress. Clear? Okay, then

// returns null
Party r = congress.get(new HonestPerson("Mother Teresa"));

Again we get a null, because Mother Teresa is not in Congress. We
could have known that without asking, because no Politician is an
HonestPerson and hence no HonestPerson can be in our map, but if
we ask anyhow the map is perfectly capable of delivering the right
answer: Mother Teresa is not a member of Congress. There is nothing
wrong with asking a self-answering question, like "What color was
George Washington's white horse?"

When calling get() on a Map, the program must already be ready
to deal with the possibility that the Map does not contain the
offered key, so offering an "impossible" key merely exercises that
code path. If a program has reason to believe that every key it
asks about is in fact in the Map, "deal with" may be merely "ignore
until you get a NullPointerException," but that's not the Map's
fault: You ask for something that's not there (that, perhaps, could
not possibly be there), and you're told it's absent, and that's the
right answer.

Elsethread, I gather that you went through an unpleasant time
when you changed your `congress' from Map<Person,Party> to
Map<Politician,Party> (or something like that). You also went
around and changed a lot of get() calls to offer Politician
references, but you missed a few that were still trying to look
up Persons, with the result that you started getting nulls at
unexpected times. Well, yeah, that's always a problem when you
change something in one place and overlook some of the other
places that need corresponding changes. If you do this again, I'd
suggest changing the Map's name at the same time, from `congress'
to `bigmess' or something, and let the compiler draw your attention
to *every* place the Map is used so you can see if a change is
needed. After you've fixed them all, you can rename `bigmess' to
`congress' again -- if you like.

--
Eric Sosman
lid
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      10-30-2009
Eric Sosman wrote:
> [...]
> Map<Politician,Party> congress =
> new HashMap<Politician,Party>();
> congress.put(new Politician("Barney Frank", Party.DEMOCRATIC);
> congress.put(new Politician("Dan Lungren", Party.REPUBLICAN);


Drat! I'm missing some right parentheses here; should be

congress.put(new Politician("Barney Frank"), Party.DEMOCRATIC);
congress.put(new Politician("Dan Lungren"), Party.REPUBLICAN);

--
Eric Sosman
lid
 
Reply With Quote
 
Mike Schilling
Guest
Posts: n/a
 
      10-30-2009
Peter Duniho wrote:
> I know what I suspect: since HashMap (and Map) pre-date generics in
> Java, the types already have an overload that takes Object as an
> argument. Due to the decision to reuse the existing implementations
> for the non-reified generics feature in Java, there wasn't any
> feasible way to eliminate the possibility of passing an Object (thus the
> compile-time assurance I mentioned earlier isn't really a benefit
> available in Java), and absent that there just wasn't a strong
> argument _against_ allowing Object as an argument.


Not true. The same feature of generics that controls the arguments to put()
could have controlled the argument to get(). A deliberate decision was made
to have get(Object) instead of get(K) [1], and reification has nothing to do
with it.

1. Likewise Set.contains(Object) and Set.containsAll(Collection<?>), but
Set.addAll(Collection<E>). Very consistently, you can add only something of
the proper type, but you can look for things of any type at all.


 
Reply With Quote
 
Mike Schilling
Guest
Posts: n/a
 
      10-30-2009
Peter Duniho wrote:
> Mike Schilling wrote:
>> Peter Duniho wrote:
>>> I know what I suspect: since HashMap (and Map) pre-date generics in
>>> Java, the types already have an overload that takes Object as an
>>> argument. Due to the decision to reuse the existing implementations
>>> for the non-reified generics feature in Java, there wasn't any
>>> feasible way to eliminate the possibility of passing an Object
>>> (thus the compile-time assurance I mentioned earlier isn't really a
>>> benefit available in Java), and absent that there just wasn't a
>>> strong argument _against_ allowing Object as an argument.

>>
>> Not true. The same feature of generics that controls the arguments
>> to put() could have controlled the argument to get(). A deliberate
>> decision was made to have get(Object) instead of get(K) [1], and
>> reification has nothing to do with it.

>
> Perhaps you're simply misunderstanding what I'm saying. It's not true
> that what I wrote is not true.
>
> In .NET, for example, there is _no way_ to call the Add() method of a
> generic collection without providing an element of the correct type.
> Not even using reflection can it work.


Right. Reification gives you that.

>
> In Java, you have type erasure. As long as you're dealing with
> generically-declared accesses to the data structure, you have the
> protection of the specific declared type. But this is easily
> circumvented. There's no way at compile time for Java to _guarantee_
> that you haven't misused the type, never mind at runtime.
>
> To the extent that this is a risk, we just live with it for methods
> that modify the collection. Java protects us as best it can, and you
> have to go at least a little out of your way to circumvent the type
> protection.
> But for harmless scenarios where there's not necessarily even a data
> corruption/runtime error consequence, and some might see some benefit,
> they've actually exposed the typed erasing as part of the primary
> generic API. My suggestion is that the reasoning might be that since
> some people might actually _want_ to do this, and there's no way to
> 100% protect against it, they went ahead and opted for slightly more
> utility.


OK, I see what you're saying now, and I can't categorically call it untrue.
Clearly the designers thought that someone might want to do that, since they
didn't make the slight effort that would have prevented it. But I don't see
any evidence whether they would have made that same decision with a newly
created, reified collections framework.


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      10-30-2009
Peter Duniho wrote:
> [... in re get(Object) on a Map<K,V> ...]
> I see a particular benefit in constraining the
> argument; in particular, it allows one at compile time to avoid writing
> code that you know will always fail. So there must be some other
> benefit that offsets that one, justifying the current design.


Maybe the debate is about this word "fail." In one sense,
if you look for something in a Collection that doesn't contain
it, the search "fails." In another sense, it "succeeds" in
determining the absence of the sought object. It is not a
given that finding something in a Map is the "normal" case and
finding that it's not there is a "failure." An result of "not
there" can even be the desired outcome: Imagine a demolition
foreman checking for people in the building before firing the
explosives to bring the thing down.

A negative answer is not ipso facto a "failure." Yes, it
is a Good Thing to prevent failures -- but that's not the same
thing as preventing negative answers.

--
Eric Sosman
lid
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
reuse HashMap$Entry (or HashMap in total) to avoid millions of allocations Vince Darley Java 4 03-02-2010 07:48 AM
java.util.Properties extending from HashMap<Object, Object> insteadof HashMap<String, String> Rakesh Java 10 04-08-2008 04:22 AM
HashMap vs TreeMap Ahmed Moustafa Java 2 08-10-2003 03:31 AM
Re: Properties2 extends Hashmap, pros and cons? Jon Skeet Java 5 07-08-2003 06:44 PM
HashMap Sanjay Kumar Java 2 07-05-2003 07:10 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57