I have for instance this Map:
Map<String, Integer> map = new HashMap<String,Integer>();
than I put some values:
map.put("a", 2);
map.put("b", 3);
Than I have this class to serialize this object:
public class MapObject implements Serializable {
private static final long serialVersionUID = 1L;
Map<String, Integer> map = new HashMap<String, Integer>();
public MapObject(Map<String, Integer> map) {
this.map = map;
}
}
I do this because I'm working with sockets and I want to pass a map object from the client to the server using ObjectInputStream and ObjectOutputStream.
Now what I want to ask is if I can store this Map object in the server, for instance
MapObject mo;
Is it possible to store this object in another Map?
Regards
You are mixing two questions together. Don't know which you are asking:
Can you transport a hierarchical map thro ObjectOutputStream?
How to map a map to a map?
If you are asking question 2, you should not mention even mention question 1 because it confuses the question. OR are you asking both questions?
Answer to question 2:
Map<String, Map<?,?>> mapOfMap = new HashMap<String, Map<?,?>>();
Map<String, Integer> mapA = new HashMap<String, Integer>();
mapOfMap.put("a", mapA);
Answer to question 1:
Of course.
...
To answer your further questions:
Set of all the keys and its iterator,
Set<String> keys = mapOfMap.keySet();
Iterator<String> iterator = keys.iterator();
Look at http://code.google.com/p/synthfuljava/source/browse/trunk/common/org/synthful/util/HashTreeNode.java,
to see an example of what can be done with map of maps.
That tree hash node was written (poorly) in 2004 (and needs to have fluff like toStringBuffer removed), but it does adequately to illustrate an xpath addressable hash tree. I have another version for GWT with the fluff removed somewhere else.
Related
I've been trying to create a class that will model a scenario I've come up with. It will involve a map with string keys and values.
I need to create an instance variable used to reference the map object, and a constructor that creates the empty map and assigns it to the map instance variable.
I've been messing around with map objects but not creating a class using them, and I've hit a mental block!
What's the proper way to actually get a map object?
public class TheClass {
private Map<String, String> theMap;
public TheClass() {
theMap = new HashMap<>();
}
}
public class Demo {
Map<String,String> map = null;
public Demo()
{
map = new HashMap<String,String>();
}
}
If you want to use HashMap which is Map implementation you can do it like that:
Map<String, String> map = new HashMap<String, String>();
or
Map<String, String> map = new HashMap<>();
in Java 7.
You can also use other implementations like TreeMap.
You can use the HashMap which is an implementation of Map
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
Map<String,String> map = new HashMap<String,String>();
map.put("key1", "Value1");
map.put("Key2", "Value2");
This question already has answers here:
How to swap keys and values in a Map elegantly
(9 answers)
Closed 9 years ago.
I want to write a method which will take a map as parameter and replace the keys and values of that map by values and keys. I am trying to do it like this:
public class HashMapKeyValueInterchange{
public static Map<String, String> getMyMap(ConcurrentHashMap<String, String> m){
Map<String, String> map2 = new HashMap<String, String>();
for(Entry<String, String> e:m.entrySet()){
map2.put(e.getValue(), e.getKey());
}
return map2;
}
public static void main(String[] args) {
ConcurrentHashMap<String, String> map1 = new ConcurrentHashMap<String, String>();
map1.put("ajay", "btech");
map1.put("manas", "mca");
map1.put("ashu", "mba");
}
}
Using this method I can get a new map(map2) with exchanged key and values, but I want map1 to be exchanged
It is availabe, no need to reinvent the wheel, if you use google collection library Guava then you can use BiMap<K,V>.
It is a map that preserves the uniqueness of its values as well as
that of its keys. This constraint enables bimaps to support an
"inverse view", which is another bimap containing the same entries as
this bimap but with reversed keys and values.
Implementation of BiMap are EnumBiMap, EnumHashBiMap, [HashBiMap][2], ImmutableBiMap
Use this code
public static ConcurrentHashMap<String, String> getMyMap(ConcurrentHashMap<String, String> m){
ConcurrentHashMap<String, String> map2 = new ConcurrentHashMap<String, String>();
for(Entry<String, String> e:m.entrySet()){
map2.put(e.getValue(), e.getKey());
}
return map2;
}
public static void main(String[] args) {
ConcurrentHashMap<String, String> map1 = new ConcurrentHashMap<String, String>();
map1.put("ajay", "btech");
map1.put("manas", "mca");
map1.put("ashu", "mba");
map1 = getMyMap(map1);
}
If the question is if the code works, the answer is yes. Some comments:
If you want your code tested, you need to call getMyMap with map1 or other adequate parameter.
If you want to see any output, you need to write something like System.out.println( getMyMap( map1 ) );
I'd strongly recommend to use Map instead of ConcurrentHashMap as getMyMap's 1st parameter type, so the function is more general an works with other maps.
To make your code even more general, make it:
public static <K,V> void getMyMap(Map<V,K> output,Map<K,V> input) {
for(Entry<K,V> e: input.entrySet() ) {
output.put(e.getValue(), e.getKey());
}
}
This will accept a bigger variety of Map's and store the output in any type of Map is passed as the first parameter. Example:
getMyMap(new TreeMap<String,String>(),map1);
getMyMap(new HashMap<String,String>(),map1);
A final point is that you don't specify a behavior when values are repeated. The assumption above is that either this case does not occur or that any key in the input map is acceptable as value in the output one.
BiMap is a good choice for this kind of operation
A BiMap is a Map that
allows you to view the "inverse" BiMap with inverse()
ensures that values are unique, making values() a Set
BiMap.put(key, value) will throw an IllegalArgumentException if you attempt to map a key to an already-present value. If you wish to delete any pre-existing entry with the specified value, use BiMap.forcePut(key, value) instead.
BiMap<String, Integer> userId = HashBiMap.create();
String userForId = userId.inverse().get(id);
Look here for more information
I have a set with multi-dimensional hashmaps, like so:
Set<HashMap<String, HashMap<String, String>>> myHashSet = new HashSet<HashMap<String, HashMap<String, String>>>();
I am having trouble removing a HashMap entry. I know the key for the top level hashmap, but do not know any data in the underlying hashmap. I am trying to remove a hashmap entry in the set in these ways:
I.
Set<HashMap<String, HashMap<String, String>>> myHashSet = new HashSet<HashMap<String, HashMap<String, String>>>();
... Add some hashmaps to the set, then ...
String myKey = "target_key";
setInQuestion.remove(myKey);
II.
Set<HashMap<String, HashMap<String, String>>> myHashSet = new HashSet<HashMap<String, HashMap<String, String>>>();
... Add some hashmaps to the set, then ...
String myKey = "key_one"; //Assume a hashmap has been added with this top level key
HashMap<String, HashMap<String, String>> removeMap = new HashMap<String, HashMap<String, String>>();
HashMap<String, String> dummyMap = new HashMap<String, String>();
removeMap.put(myKey, dummyMap);
setInQuestion.remove(removeMap);
Neither of these methods work. How would I go about removing an entry in the set if I only know the top level hashmap's key?
Collection.remove() requires object equality. the various jdk Map implementations implement equality to mean all keys/values must match. Since none of the objects you are passing to the remove() call would be "equal" to any of the Maps in the Set, nothing is being removed.
the only way to do what you want is to iterate through the Set yourself to find the matching Map (or, make the Set into a Map keyed on that special key).
Thanks jtahlborn for the guidance. Wanted to post the solution I've found as a result of your answer:
String myKey = "Key_In_Question";
Iterator mySetIterator = myHashSet.iterator();
while(mySetIterator.hasNext()) {
HashMap<String, HashMap<String, String>> entry = (HashMap<String, HashMap<String, String>>) mySetIterator.next();
if(entry.containsKey(myKey)) {
myHashSet.remove(entry);
}
}
Sorry I couldn't post this as a comment. I wanted to point out that #jtahlborn's point about Map equality is a well-defined part of the contract... see Map.equals.
... two maps m1 and m2 represent the same mappings if m1.entrySet().equals(m2.entrySet()). This ensures that the equals method works properly across different implementations of the Map interface.
Map.Entry.equals is worded similarly.
... two entries e1 and e2 represent the same mapping if
(e1.getKey()==null ?
e2.getKey()==null : e1.getKey().equals(e2.getKey())) &&
(e1.getValue()==null ?
e2.getValue()==null : e1.getValue().equals(e2.getValue()))
This ensures that the equals method works properly across different implementations of the Map.Entry interface.
I need to call an external API with an ArrayList of HashMaps holding several predefined key-value pairs each. An example:
ArrayList<HashMap<String, String>> arrayListHashMap = new ArrayList<HashMap<String, String>>();
{
HashMap hashMap = new HashMap<String, String>();
hashMap.put("key", "A key");
hashMap.put("value", "B value");
arrayListHashMap.add(hashMap);
}
{
HashMap hashMap = new HashMap<String, String>();
hashMap.put("key", "B key");
hashMap.put("value", "A value");
arrayListHashMap.add(hashMap);
}
Now I need to sort this construct on the contents of the "value" key. This sort would result in the "key=B key/value=A value" entry as the first one in the arrayListHashMap.
Any help is highly appreciated.
HJW
You need to implement a Comparator<HashMap<String, String>> or more generally Comparator<Map<String, String>> which just extracts the value assocated with the value key, then use Collections.sort. Sample code (with generalization for whatever key you want to sort on):
class MapComparator implements Comparator<Map<String, String>>
{
private final String key;
public MapComparator(String key)
{
this.key = key;
}
public int compare(Map<String, String> first,
Map<String, String> second)
{
// TODO: Null checking, both for maps and values
String firstValue = first.get(key);
String secondValue = second.get(key);
return firstValue.compareTo(secondValue);
}
}
...
Collections.sort(arrayListHashMap, new MapComparator("value"));
You can use the below solution to achieve it:
arrayListHashMap.sort(Comparator.comparing(m -> m.get("value"), Comparator.nullsLast(Comparator.naturalOrder())));
(This is not an answer to the asked question - Jon did this already -, but the comment field is too small for this.)
Your data structure looks like you misunderstood the key-value structure of maps (and Hash maps in your example).
A Map can contain any number of keys, and for each key also a value. A pair of key and value is given by a Map.Entry (which can be obtained by the entrySet() method of the map). If you then want to sort by key, simply use a SortedMap (like TreeMap) instead of the usual HashMap.
You are emulating the individual entries by a HashMap each, then putting them all in a ArrayList ... :-/
Here what I would have done in your example:
Map<String, String> map = new TreeMap<String, String>();
map.put("B key", "B value");
map.put("A key", "B value");
System.out.println(map); // already sorted
i am reading data from a text file and want to store HashMap in another HashMap..
HashMap<string,HashMap<string,value>>
how to store data and retrieve it?
any sample code will be appreciated...
thank u
Example:
Creating and populating the maps
Map<String, Map<String, Value>> outerMap = new HashMap<String, HashMap<String, Value>>();
Map<String, Value> innerMap = new HashMap<String, Value>();
innerMap.put("innerKey", new Value());
Storing a map
outerMap.put("key", innerMap);
Retrieving a map and its values
Map<String, Value> map = outerMap.get("key");
Value value = map.get("innerKey");
Creating two Simple Hashmaps: InnerMap and OuterMap
HashMap<String, HashMap<String, String>> outerMap = new HashMap<String, HashMap<String,String>>();
HashMap<String, String> innerMap = new HashMap<String, String>();
Populating the HashMaps
innerMap.put("InnerKey", "InnerValue");
outerMap.put("OuterKey", innerMap);
Retreiving values from HashMaps
String value = ((HashMap<String, String>)outerMap.get("OuterKey")).get("InnerKey").toString();
System.out.println("Retreived value is : " + value);
You get something that looks like a 2 dimensions HashMap, so to say. Which means you need 2 String to store a value, and also to retrieve one.
You could, for example write a class to wrap that complexity, like that (untested code):
public class HashMap2D<T> {
private HashMap<String,HashMap<String,T>> outerMap;
public HashMap2D() {
outerMap = new HashMap<String,HashMap<String,T>>();
}
public void addElement(String key1, String key2, T value) {
innerMap=outerMap.get(key1);
if (innerMap==null) {
innerMap = new HashMap<String,T>();
outerMap.put(key1,innerMap);
}
innerMap.put(key2,value);
}
public T getElement(String key1, String key2) {
Hashmap innerMap = outerMap.get(key1);
if (innerMap==null) {
return null;
}
return innerMap.get(key2);
}
}
If you want methods to process more than one data at a time, it's more complicated, but follows the same principles.
This will solve the same problem using one map (although, this does not directly answer your question) by flattening two nested maps into one big map, using a double-key.
public class Key2D{
private final String outer;
private final String inner;
public Key2D(String outer, String inner){
this.outer = outer;
this.inner = inner;
}
//include default implementations for
//Object.equals(Object) and Object.hashCode()
//Tip: If you're using Eclipse it can generate
//them for you.
}
Then just create one map with double-key:
Map<Key2D, Value> map = new HashMap<Key2D, Value>();
map.put(new Key2D("outerKey", "innerKey"), "Value");
map.get(new Key2D("outerKey", "innerKey")); // yields "Value"
This gives a shorter solution. Performance wise it's probably about the same. Memory performance is probably slightly better (just guessing, though).
HashMap in HashMap will cause problems in readability especially when it goes beyond two levels. I assume that when you read data from a text file you want to categorize the inputs from rows and columns which should be similar to multi-level categories or category within a category. If you can post the sample data and your intention, I could come up with a Custom class example.
public class Category {
private List<Category> subCategories;
private List<Item> items;
}
The above data structure will help you solve any level of nesting while categorizing data. This example is specific to a store items' classification.