tags:

views:

222

answers:

8

Can I have an hashMap with say ID as my key and info, name, quantity as my values?

ok, say I have a class (Products) already that sets my variables, getters and setters. In my Invoice class, which is where the hashMap would be. Would I put like:

private HashMap<String, Products> keys = new HashMap<String, Products>

I'm not quite sure how to access the HashMap though. Say I implement a class that allows me to add and remove invoices from the HashMap, I do not know what the values would be:

keys.put(??value of id??,??not sure what goes here??);
+17  A: 

Sure. Make another class that contains your info, name and quantity and put that as the value of your HashMap.

Starkey
and you might want to keep the id as well if you need later on? :)
Joset
Same affect can be achieved with HashMap<Integer, HashMap<String,Object>>, and you do not have to create a new class
Luxspes
@Luxspes: are you charged for each class you create?
Michael Petrotta
+1 Create a new class, please, for the sanity of the programming world.
ColinD
I am not charged ;-), and I am well aware of the FearOfAddingClasses anti pattern ( http://c2.com/cgi/wiki?FearOfAddingClasses ). But even then, sometimes (simple problems, querying combinatorial explosion), it is much easier and convenient to create a HashMap instead of a Class.
Luxspes
@Michael Petrotta: Are you paid a bonus each time your create a new class ? ;-)
Luxspes
+1  A: 

How about HashMap<Integer, ArrayList<String>> ?

UPDATE: Please try to avoid this, this is a better approach.

zengr
I think you got it backwards, ArrayList<HashMap<String,Object>> would be write, but not HashMap<Integer, ArrayList<String>> (because there would be no way to know which of the elements in the arraylist is your "info", "name" or "quantity"
Luxspes
If you have 4 attributes of 1 ID, why can't you save in that manner?
zengr
because there would be no way to know which of the elements in the arraylist is your "info", "name" or "quantity"
Luxspes
well, you are right, but that's is something which can be assumed.
zengr
avoiding assumptions like those can make your code much easier to read and maintain, specially on a big team, on in a very long project, or when you are given the task to maintain the code of someone that no longer works in the company ;-)
Luxspes
Please don't do this.
ColinD
Because readability of the code will be a problem?
zengr
It's essentially using a list as a terrible imitation of an object, one that doesn't (without comments everywhere it's passed to) give you any information on what its fields are supposed to be or even how many fields there are, nor does it allow you to give those fields different (visible) types. Readability will certainly be an issue, yes.
ColinD
While I agree that a List is a not a good imitation of an object, I believe a Map can sometimes be a good imitation for an object, specially for simple problems, or for database intensive applications with interative querying where the combinatory explosion would make creating a class for each query result a nightmare
Luxspes
A: 

Of course, you could for example declare it like this: HashMap<Integer, HashMap<String,Object>> You use the outer hashmap to link your id with your inner HashMap, and in the inner one, you create keys "info", "name", "quantity" and associate values with them.

Of course, you could also use an ArrayList as the outer collection (it could be a better match for your ID: ArrayList<HashMap<String,Object>> that way you have indexed (id based) access to each of your "info", "name", "quantity" hashmap "records"

Luxspes
As I've argued elsewhere, this is generally not the best idea.
ColinD
Not the best idea for your requirements? or not the best idea from the requirements of the person who asked the question?. Forgive me, but I believe you are not being objective.
Luxspes
+6  A: 

No, but the best way is to wrap the information you want to keep in the map in a class:

public class Info {
  private String info;
  private String name;
  private int quantity;

  ...

  public Info(String info, String name, int quantity) {
     ...
  }
}

Then do this to put something in the map:

Info info = new Info("info", "name", 2);
Map map = new HashMap<Integer, Info>();
map.put(22, info);

And do this to get something out:

Info info = map.get(22)
Javid Jamae
Same affect can be achieved with HashMap<Integer, HashMap<String,Object>>, and you did not have to create a new class
Luxspes
@Luxspes: No. Unlike a class, a `HashMap<String, Object>` only tells you "hey guys, there might be some strings associated with some objects! or maybe not!". A class can tell you exactly what fields there ARE, and what their types are too! Creating a new class is not a big deal.
ColinD
@ColinD: Not a big deal, unless you are using it to represent the result of an database query that can be built interactively by the user, then, the flexibility of the Map makes it a perfect solution (and the combinatorial explosion of creating a class for each possible combination the user chooses, makes it unusable)
Luxspes
@Luxspes: Sure, there may be situations where a map is appropriate to use for this, but those are rare and can be recognized by someone with experience. Someone new should be strongly encouraged to do what's normally the right thing (creating a class) lest they get the idea that a map is what they should always use when they want to group fields together.
ColinD
@ColinD: In my experience, pretty much anyone knows how to create a class, and pretty much noone knows that a map can be used as a dynamic replacement for it... Unless they are Ruby, Smalltalk or Objective-C developers, for them the distinction blurs thanks to the dynamic nature of their languages.
Luxspes
@ColinD: Also remember the question was: "Can I have an hashMap with say ID as my key and info, name, quantity as my values?", from that perspective, I do not see why using a class is a better answer that using a HashMap (in fact, a HashMap is what was asked for...no?)
Luxspes
@Luxspes: The asker of the question seems to be pretty new at this. We should be giving him the best way of doing what he wants to do, which is almost certainly to use a class. I really don't understand what makes you think a map is even close being a good choice, given that he clearly doesn't need a dynamic set of fields.
ColinD
@ColinD: Well, he did not ask "I have a ID as my key and info, name, quantity as my values, what is the best data structure to represent that?". He asked "Can I have an hashMap with say ID as my key and info, name, quantity as my values?", so I am (only guessing) that he wants to learn about what is possible with HashMaps (and not just about what "in general" is the best data structure). What makes you think he wants to learn about classes? did he mentioned them anywhere in the question?
Luxspes
I don't think he *knows* that a class is what he should use here! That's why people answered the question to tell him! I don't think he would have had any reason to ask the question if he knew that. And if he did, then perhaps he wanted to know if there were a better way than using a class. Which there isn't, really. People don't need to know the answer to ask a question. =/
ColinD
Mmmm... now I am curious... lets say he actually wanted to know if it was possible to have an HashMap with say ID as my key and info, name, quantity as my values, using HashMaps... how do you think he should have written the question? should he list everything he does not want? (that list can be pretty long)
Luxspes
@Luxspes: I don't feel like anyone would have a reason to ask such a question... it's too specific about the implementation details, to the point that if you ask it you would almost certainly already know the answer. They might, say, ask how they could represent the results of a query when the set of fields it returns may vary, in which case a `Map<String, Object>` might be a good suggestion.
ColinD
@Luxspes - knowing that a map contain single keys and single values is pretty basic. My assumption when answering the question was that Jack was a beginner, so I suggested a more elegant design. The solution you're providing is obviously for an advanced corner case and seems obviously out of context for this question. If he knew he could have used a class, he could have said "I know I could use a class here, but I'm really interested in knowing..."
Javid Jamae
so are you talking about having the Info class and the hashmap in a separate class? My program is suppose to add content by the user, not by me. So I thought that I would need to use getters and setters. I actually have exactly what you put in your first block of code with setters and getters too in a class. in another class i have the hashmap but I'm just dont know the syntax to use such as map.put(getID(), info)?
Jack
A: 

You could have ID as key and a List or Set (Collection in general) of objects as value.

fastcodejava
A: 

Not exactly.

A Map defines a strictly 1 to 1 relationship between keys and values. One key in the map has one value.

If you want to associate multiple values with one key you need to do one of the following:

  • Define a Values class to represent the values as a single object; e.g. as per @Starkey's and @Javed's answers. Then the map becomes a Map<String, Values> (assuming that the key type is String).

  • Define the map as a Map<String,List<Object>> or Map<String,Object[]> and represent the values as an untyped list / array

  • Define the map as a Map<String,Properties> or Map<String,Map<String,Object>> and represent the values as the Java equivalent of an associative array.

Of these, the first option is both the safest (smallest chance of runtime errors), the most efficient and the best style.

(Aside: an Apache commons MultiMap might be considered as another possibility, but the conceptual model and APIs don't really match this use-case.)

Stephen C
A: 

Sure. Depending on how flexible your datastructe is you can use a Hashmap a la:

  • HashMap<IdType, List<String>>, with IdType String or Integer, depending on the Keys you like to use.
  • HashMap<IdType, String[]>
  • HashMap<IdType, YourObjectType>, with YourObjectType beeing a Object you defined yourself, holding the values you like

YourObjectType can of course be anything you can define as an Object. Also another HashMap if you like.

erikb
A: 

One of the concerns while using a Map would be use of hardcoded keys. If the key is a string, and the key changes. Can consider using a constant instead of a hardcoded string.

Having a dedicated class has the benefit of compiler to check for name changes. However, as mentioned in the earlier comments.. It can become a concern...

In my opinion both are feasible. We need to weigh which option is better depending on the situation

Siri