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??);
Sure. Make another class that contains your info, name and quantity and put that as the value of your HashMap.
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)
How about HashMap<Integer, ArrayList<String>> ?
UPDATE: Please try to avoid this, this is a better approach.
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.)
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.
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
Create an object that encapsulates the four together. Something like:
public class Foo {
private String s1;
private String s2;
private int v3;
private MyObject obj1
// constructors, getters, helper functions.
}
I think MultiMap from google library could serve the purpose
https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html
Multimap<String, String> map = ArrayListMultimap.create();
String key = "uniqueKey";
map.put(key, "value1");
map.put(key, "value2");
map.put(key, "value3");
System.out.println(map);//{uniqueKey=[value1, value2, value3]}
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"
You could have ID as key and a List or Set (Collection in general) of objects as value.
Related
I want to design a HashMap which has multiple Strings/Enum's as composite key. I want to change the functionality, such that if the map is filled with an enum/string value as "default", then it will match to anything in the search
The Key here is matching anyvalue to "default", if the specific value does not exist.
let's say the following class is the Key class of this HashMap:
class KeyClass{
String val1;
String val2;
String val3;
}
HashMap<KeyClass, String> randomMap = new HashMap<>;
randomMap.put(new KeyClass("abc", "default", "efg"), "value1");
randomMap.put(new KeyClass("abc", "def", "efg"), "value2");
randomMap.get(new KeyClass("abc", "wef", "efg")); // should return "value1" as "wef" should match to default,
randomMap.get(new KeyClass("abc", "def", "efg")) // should return "value2", as it explicitly matches
Specifically I'd like design suggestions for such a Map structure (for instace would it work with two different maps etc.) , or how to implement the hashCode function for such a key class if it is at all possible.
This is not possible if I understand your question correctly. I think you need to use something else than HashMap for this.
HashMap uses the hashcode/equals methods of the key-class for matching, so I interpret your question as how to implement those methods.
hashcode is actually easy. I think your only option would be to return a constant. This is a stupid idea, but it would be necessary if "default" should match anything.
equals is not possible to implement. The matching you describe would not be symmetric and transitive as required by the documentation (https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)).
My problem is that there are 3 variables, say a,b,c
First, information a,b,c needed to be input and stored.
For example a=Tom, b=school A, c=1402
Then, I can get the above information by entering "Tom", in this case, if there is another Tom in school B,that message would also be printed out.
or by entering "Tom, school A", then only that Tom would be printed out. In this problem, their would be no duplicates if a and b are both locked.
Well, my view is that a must be a key, and a+b can be a composite key. So firstly I thought of a HashMap, however, HashMap has only one key to one value. So I intended to use 2 maps but this could not make use of composite key.
So are my thoughts correct? Or are there any better data collections in Java could be used in this case?
Thank for your time!
There is no off the shelf data structure in Java for your need. There are multi valued map implementations in Apache Commons and Google Guava Collections but not in core Java.
But , In my opinion, you can implement it with a map declaration like - Map<String, List<String>> or Map<String, List<Student>> depending on whether you are keeping your student details as concatenated strings or as a Student class.
While populating the map - you will make two entries in map for first row / student , once for a and another entry for a+b concatenated.
Then while making entries for subsequent rows , you should first check if key exists in map or not, if it exists, you get the value , append new value and store again.
Record a=Tom, b=school A, c=1402 will have two entries then comes record a=Tom, b=school B, c=1403 and you will append record for key = Tom and add a new entry for TomschoolB so in total three entries in map for keys - Tom , TomschoolA and TomschoolB. Key Tom will have two items in value list while rest two will have single items.
Your lookup code should follow key calculation logic as key creation logic i.e. string concatenation or any other things as you wish.
This is just give a rough idea that multiple values can be handled via list.
Edit : From your comments, you look confused so below is code to implement the idea. You can tweak and extend it as you wish.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MultiValuedMap {
private static Map<String,List<String>> storage = new HashMap<>();
public static void main(String[] args) {
store("Tom","Tom,schoolA,1402");
store("TomschoolA","Tom,schoolA,1402");
store("Tom","Tom,schoolB,1402");
store("TomschoolB","Tom,schoolB,1403");
storage.forEach((key,value) -> System.out.println("key:"+key+",value:"+value));
}
private static void store(String key, String value){
if(storage.containsKey(key)) {
List<String> newList = storage.get(key);
newList.add(value);
storage.put(key,newList);
}else{
List<String> values = new ArrayList<String>();
values.add(value);
storage.put(key,values);
}
}
}
Output:
key:Tom,value:[Tom,schoolA,1402, Tom,schoolB,1402]
key:TomschoolB,value:[Tom,schoolB,1403]
key:TomschoolA,value:[Tom,schoolA,1402]
When you feel ambiguous of using any existing datastructure I suggest you to create your own data structure.With that you can create any methods and anything according to your need.
Here is a part of my Person class:
#Entity
public class Person {
#ElementCollection(fetch = FetchType.EAGER)
private Map<String, String> externalPropertyMap = new HashMap<>();
}
So i need to select every Person with exact key and value from this map. For example select every Person with key="prefferedNumber" and value="123456"
How can i do this?
Actually this is not accurated:
So i need to select every Person with exact key and value from this map
You have a HashMap, a Map implementation which don't allow repeated keys, so, you just will get one single value for each key from the HashMap.
To achieve this you need to use another Map implementation, but don't worry, someone has your problem already:
Try this implementation
MultiMap from ApacheCommons
A MultiMap is a Map with slightly different semantics. Putting a value into the Map will add the value to a Collection at that key. Getting a value will return a Collection, holding all the values put to that key.
I am trying to create a data structure in Java that is a Vector into which some information about an unknown number of entities will go from a database. When it comes to this information, I only care about 2 fields. Also, it is required that when I iterate through this Vector, I can extract these two fields (say, String) in pairs. Schematically speaking,
String s1 = Vector[1].Field1, String s2 = Vector[1].Field2
Is this even possible? Does anyone know a more efficient way to achieve this?
Note: I would like to keep it in a single Vector because I pass it to another class for processing.
Use
public class Entry {
public String field1;
public String field2;
}
List<Entry> vector = ...;
Why not using Map<String, String>
But map will be unique keys
Also you can create your own Class and pass it to the Vector<yourclass>
Here's how I would do it :
Create an object Pair with 2 attributes : field 1, field 2
Add this object to your vector.
Use a Vector of maps, with keys value1 and value2. Vector<Map<String, String>>.
Or define a new object with two attributes ( I suggest the second option )
I need something like a property bag to throw key value pairs into.
I want to create list of such objects, initialize them in bean and then use the list to render table in JSF template.
I know how to do it, but I want to avoid creating some special class for that case, like OrderLineItem and using List<OrderLineItem>.
I do not want to define new class.
In PHP I could use StdClass.
StdClass is a sparsely documented class in PHP which has no predefined members.
$object = new StdClass;
$object->foo = 'bar';
But, as far as I know, Primefaces <p:dataTable> list item must be an object with getter.
If I want to reference <h:outputText value="#{item.title}" />, my list object should have getTitle() method.
Is there any walkaround in my case or I really need to define special class to make life easier?
Thanks.
When you want a simple key/value table, then the HashMap might be what you are looking for.
Map<String, String> myMap = new HashMap<>();
myMap.put("foo", "bar");
System.out.println(myMap.get("foo")); // outputs "bar"
This example matches Strings to Strings, but you can use HashMaps to map any type to any other type. You can even create a Map<Object, Object> to create a weakly-typed map which maps anything to anything. But for most use-cases you would rather use a more specialized form.
What you need is a Map.
You can store key-value pairs in it pretty easy:
Map<KeyClass, ValueClass> myMap = new HashMap<KeyClass, ValueClass>();
Use the put method to put data in it. If you use simple String values it will be like this:
myMap.put("key", "value");
I don't know if I understood you well. But I think you mean SelectItem or JsfMap.
I would recommend to use an anonymous class:
return new HashMap<String, String>() {
{
this.put("key", "value");
}
};