Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Map vs. HashMap for hashes  RSS feed

 
Mike Smith
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In class, our teacher said it's best to instantiate a hash via:



I'm not sure I understand why. If I re-do all the code from class and homeworks with variable type HashMap (as opposed to Map, like he said to do), everything works just the same.

Thanks
[ May 05, 2007: Message edited by: Mike Smith ]
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That recommendation goes with the general guideline to write to interfaces when you can. If you declared your variable as HashMap you might write your code to depend on some method that HashMap has and the Map interface does not. Then it would be hard to change your variable to a TreeMap or a custom Map.

Similarly, if you passed the map around as a parameter, you might have code like this:

Then if you had to use TreeMap, you couldn't just change to a TreeMap in one place. You'd have to go around and change all the references to HashMap to TreeMap. But if your method was written ...

... then you could pass any kind of Map into the method.

In small school assignments the flexibility offered by interfaces may not make much sense. But getting in the "write to interfaces" habit will do you well in large systems.

PS: I don't know if HashMap even has any methods not in the Map interface, but if it did and you really had to use one of those methods, you'd have to declare as HashMap from the beginning. Write to interfaces when you can which may not be all the time.

Does that seem to fit with your instructor's ideas?
 
Hung Tang
Ranch Hand
Posts: 148
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Map is an interface whereas HashMap is an implementation. A good principle to follow is always design your software around the concept of interfaces so it'll protect you from harassment from your users when you make an underlying change to your software (in your case the implementation of Map used)
[ May 05, 2007: Message edited by: Hung Tang ]
 
Mike Smith
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot, makes sense.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think the lesson here is more general than just using interfaces. It's usuall a good idea to declare your variables with the most general type you can - whether it's an interface or a class. Some classes were designed without interfaces, and you may need to use them anyway. For example a FileInputStream extends InputStream, an abstract class - but there's no interface that allows you to read(). So to use a FileInputStream, I would usually write

The idea is that InputStream is more general than FileInputStream, so writing the code this way gives me more flexibility if I later want to use a SocketInputStream instead. Or if I want to wrap the FileInputStream inside another stream, like BufferedInputStream. Same idea as using Map rather than HashMap, even though Map is an interface and InputStream is a class.

Alternately, sometimes there is more than one interface that you can use. If you're using an ArrayList, you might want to declare it as a List - or you might be better off declaring it as a plain Collection instead. If you don't need any of the List-specific methods like get(int), then Collection is probably the better option. But if you do need the more specific methods like get(int), don't hesitate to declare the variable as a List instead. Use the most general type (class or interface) that meets your need. But don't let that stop you from using a more specific type if you need to.
 
Mike Smith
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fascinating and incredibly helpful. Thanks for taking the time to explain. I've always been a bit foggy on the whole concept of making a variable as general as possible and still getting the results and methods you want. I'm curious though, why the system doesn't allow you to just declare every variable ever as type Object, since it is the root of all other classes? I say this, yet when I test it, it clearly doesn't work. I feel kind of silly asking this...Like I'm just imagining that if all methods took parameters of type Object, and every variable was of type Object (even though they may be pointing to instances of more specific classes), and I'm having a hard time seeing where the problem would be.

Another very naive question, but something I keep thinking of every time I have to import stuff like LinkedLists: why does the compiler not import every part of the API automatically? Is it to save space/resources?
 
Ernest Friedman-Hill
author and iconoclast
Sheriff
Posts: 24217
38
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Some languages do work that way, where everything is an "Object". Some things that the Java compiler does are instead done by the runtime system in a language like that -- i.e., if you try to call "read()" on an ArrayList, the Java compiler would tell you that ArrayList has no such method, and refuse to build your program. But in some languages -- Ruby is one popular, current example -- you don't find out about the problem until you actually run the program, and then it fails. Neither system is necessarily better than the other, although in general, the more work that your compiler can do, the less needs to be done while the program runs, meaning it can be faster.

About the importing: you'll find that the Java APIs, which contain thousands of classes, contain many example of duplicate class names. For example, there's a java.awt.List as well as a java.util.List. If the compiler automatically imported all the APIs -- well, then what would it do here? More troubling, perhaps, is that there are so many classes in the API that you're likely to find some whose names duplicate those of some of your own application classes, and again, this would cause problems of various kinds.
 
Nicholas Jordan
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mike Smith:
Fascinating and incredibly helpful.

Yes it is, I was reading their replies. These guys a remarkably perceptive of several issues.

I'm curious though, why the system doesn't allow you to just declare every variable ever as type Object.

Try to write a compiler, or just guess at what it would take.

I feel kind of silly asking this...

Don't, your questions are well informed and insightful.

... and I'm having a hard time seeing where the problem would be.

Comes mostly from trying to run large projects where there are many people writing code. (i think)
Another very naive question, but something I keep thinking of every time I have to import stuff like LinkedLists: why does the compiler not import every part of the API automatically?

The problem, generally, is called namespace collisions. Dr. Ernest Friedman-Hill's answer is the best wording I have seen of the matter. After you try to write a lot of code, the reasoning will become all too apparent.

See: http://mindprod.com/jgloss/gotchas.html

scroll down to the text: "The designers of Java never took the time to clean up all the methods and make them use consistent conventions" which is perhaps misleading because that wording glosses over some factual matters from the real world, where seeing where the problem would be becomes very apparent when you try to write useful, working code.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!