Can I access my nestedMap in my iterator when the nestedMap is created in the put() method, like this:
#Override
public String put(final String row, final String column, final String value) {
/**
* Second map which is contained by centralMap, that contain Strings as
* Keys and Values.
*/
Map<String, String> nestedMap;
if (centralMap.containsKey(row))
nestedMap = centralMap.get(row);
else
nestedMap = new HashMap<String, String>();
if (!nestedMap.containsKey(column))
counter++;
centralMap.put(row, nestedMap);
return nestedMap.put(column, value);
}
and the centralMap is declared as an Object-Variable,
private final Map<String, Map<String, String>> centralMap;
but instantiated just in the constructor, like this:
centralMap = new HashMap<String, Map<String, String>>();
the method i'm trying to implement is the remove method:
#Override
public void remove() {
for (Map<String, String> map : centralMap.values()) {
map = centralMap.get(keyName);
iteratorNested.remove();
if (map.size() <= 0)
iteratorCentral.remove();
}
}
Thanks a lot!
Not sure what you're asking exactly, but I think this is a little easier to read:
#Override
public String put(final String row, final String column, final String value) {
/**
* Second map which is contained by centralMap, that contain Strings as
* Keys and Values.
*/
Map<String, String> nestedMap = centralMap.get(row);
if (nestedMap == null) {
nestedMap = new HashMap<String, String>();
centralMap.put(row,nestedMap);
}
if (!nestedMap.containsKey(column))
counter++;
centralMap.put(row, nestedMap);
return nestedMap.put(column, value);
}
I can't quite understand what you're doing in the second stanza, so can't help you improve that. And I don't see an iterator as referred to in your question.
You're making me guess, but maybe ELSEWHERE in your program (it would really help to see more code, and a specific function prototype or statement of behavior you're seeking) you want to be able to iterate through the contents of the centralMap instance, and nested instances of nestedMap. Yes you can.
public void iterateOverAllNested()
{
for (Map.Entry<String,Map<String,String>> nested : centralMap) {
final String centralKey = nested.key();
final Map<String,String> nestedMap = nested.value();
System.out.println("Central map row/column: "+centralKey);
for (Map.Entry<String,String> entry : nestedMap) {
System.out.println(" key="+entry.key()+", value="+entry.value());
}
}
}
Note that this smells. Nested maps of untyped Strings are probably wrong. Any chance you've been writing Perl recently? I suggest you write a second SO question asking about a good data structure for your specific problem. You can include this code as your starting place, and folks will likely offer a cleaner solution.
Related
I have a map as shown below(simpleMap). Keys and values in this map change at runtime. I want to read the keys and look for existence of a string in the keys as shown below:
Map<String, String> simpleMap = new HashMap<String, String>();
simpleMap.put("language","GB");
simpleMap.put("locale","GB");
simpleMap.put("paging","");
simpleMap.put("source","Next_act");
simpleMap.put("Wizard-SectionSelection-0-Selected","");
simpleMap.put("Wizard-SectionSelection-2-Selected","");
simpleMap.put("Wizard-SectionSelection-9-Selected","");`
If any of the keys of simpleMap contains "SectionSelection" then I will return true else false as shown below.
private boolean myMethod(Map<String, String> simpleMap) {
for (String temp : simpleMap.keySet()) {
if(temp.contains("SectionSelection")) {
return true;
}
}
return false;
}
Is there a faster way of doing this?
The for loop through the set of keys is extremely lightweight both in terms of heap and CPU usage. Therefore, if you are concerned about the performance, you should stick to the definition which you have posted.
If you are looking for succinct ways, given below are some examples:
private boolean myMethod(Map<String, String> simpleMap) {
return simpleMap.keySet().stream().anyMatch(key -> key.contains("SectionSelection"));
}
or
private boolean myMethod(Map<String, String> simpleMap) {
return String.join(",", simpleMap.keySet()).contains("SectionSelection");
}
I have one Map in java like this:
Map<String index1, Map<String index 2, Object obj>> map = new HashMap<>();
I want to get my Object in the map by using index1 and index2 as lookups.
The easiest way to do this would be to use Guava's Table, if you're willing to use a third party library.
It works like this:
Table<String, String, Object> table = HashBasedTable.create();
table.put(index1, index2, obj);
Object retrievedObject = table.get(index1, index2);
You can add it to your project by following these instructions: How to add Guava to Eclipse project
If you don't want to use Guava, you have a big problem. If you try to insert an element with new first key, you have to make sure the innermap already exists. This means, every time you do put, you have to retrieve the innerMap, see if it exists, and then create it if it does not. You will have to do this every time you call Map.put. Also, you risk throwing a NullPointerException if the inner map doesn't exist when you call get on the inner map.
If you do this, should wrap your Map<String, Map<String, Object> in an outer class to manage these problems, or use Java 8's computeIfAbsent. But the easiest way is to just use Table as above.
If you make your own class to use instead of Table, it would be something like:
public class DoubleMap<R, C, V> {
private final Map<R, Map<C, V>> backingMap;
public DoubleMap() {
this.backingMap = new HashMap<>();
}
public V get(R row, C column) {
Map<C, V> innerMap = backingMap.get(row);
if(map == null) return null;
else return innerMap.get(column);
}
public void put(R row, C column, V value) {
Map<C, V> innerMap = backingMap.get(row);
if(innerMap == null) {
innerMap = new HashMap<C, V>();
backingMap.put(row, innerMap);
}
innerMap.put(column, value);
}
}
You would use this class by doing:
DoubleMap<String, String, Object> map = new DoubleMap();
Note that this answer has a lot less features than the Guava version.
Getting a Value from a Map
If I understand your question, then with an index a and b that might look like (guarding against null with a ternary or Conditional Operator ? :),
Object obj = (map.get("a") == null) ? null : map.get("a").get("b");
Using a Generic Type
And you might be more specific, like
Map<String, Map<String, Something>> map = new HashMap<>();
Something s = (map.get("a") == null) ? null : map.get("a").get("b");
Adding values to the Map
Assuming you want to add your Something value to the map that could be done with something like,
Map<String, Map<String, Something>> map = new HashMap<>();
if (map.get("a") == null) {
map.put("a", new HashMap<>());
}
map.get("a").put("b", value);
If you don't need regular access to the entire "row", but just quick access to each cell you can use the built-in Map.Entry as your key:
Map<Map.Entry<String, String>, Object> table = new Map<>();
table.put(new Map.SimpleEntry("index1", "index2"), "Hello world");
Alternatively, if you're willing to go with something third-party, several someones have already implemented tuples for Java.
If you are in a situation where you cannot pull in a third-party library easily, but you don't like the semantics of Map.Entry (which is written in terms of keys and values) you can write your own Pair class to have the same effect.
As my understanding, you can do like:
Map<String, Map<String, Object> map= new HashMap();
Map<String, Object> subMap = map.get("index1");
if(subMap != null) {
Object obj = subMap.get("index2");
}
The best solution probably depends on how this map is intended to be used:
Is it used in a limited scope, or is it part of a public API?
Are the "indices" always of type String, or do they have to be generic?
Will it always be two indices, or may you need more indices later?
...
A pragmatic solution focussed on the question as you described it would be to introduce a StringPair class that can be used for indexing. This saves you from the hassle of doing 2D-lookups of inner maps (and possible cleanups when the inner maps become empty!), does not require any third-party libraries, and is readable and efficient.
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
public class StringPairMapTest
{
public static void main(String[] args)
{
Map<StringPair, Object> map = new LinkedHashMap<StringPair, Object>();
map.put(StringPair.of("A","B"), 12);
map.put(StringPair.of("C","D"), 34);
System.out.println(map.get(StringPair.of("A","B")));
System.out.println(map.get(StringPair.of("C","D")));
System.out.println(map.get(StringPair.of("X","Y")));
}
}
class StringPair
{
private final String s0;
private final String s1;
static StringPair of(String s0, String s1)
{
return new StringPair(s0, s1);
}
private StringPair(String s0, String s1)
{
this.s0 = s0;
this.s1 = s1;
}
#Override
public String toString()
{
return "("+s0+","+s1+")";
}
#Override
public int hashCode()
{
return Objects.hash(s0, s1);
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StringPair other = (StringPair) obj;
return Objects.equals(s0, other.s0) && Objects.equals(s1, other.s1);
}
}
Generalizations to a Pair<T> or Tuple<S,T> would be possible, of course, but this did not seem to be what you have been looking for...
I have a nested HashMap:
HashMap<String, Map<String,Integer>> map = new HashMap<>();
The key for the nested map may have multiple values:
{Color={Red=4, Blue=6}}
I want to be able to return the key of the nested map that has the lowest value. In this case, if I gave the key Color from the outer map, I want to have Red returned.
Any help is greatly appreciated.
Get the inner map by key.
Get the Iterator of the inner map.
Assign the first kvp as the minimum.
Loop through the iterator checking if any subsequent kvp is less than the minimum and assign it if true.
Return the minimum's key.
Code Sample:
public static void main(String[] args) throws Exception {
Map<String, Map<String,Integer>> map = new HashMap() {{
put("Color", new HashMap() {{
put("Red", 4);
put("Orange", 1);
put("Blue", 6);
put("Yellow", 2);
}});
}};
System.out.println(getInnerKeyWithLowestValue(map, "Color"));
}
public static String getInnerKeyWithLowestValue(Map<String, Map<String,Integer>> map, String outerKey) {
Map<String, Integer> innerMap = map.get(outerKey);
// Make sure inner map was retrieved
if (innerMap != null) {
Iterator<Map.Entry<String,Integer>> it = innerMap.entrySet().iterator();
Map.Entry<String, Integer> minimum = it.next();
while (it.hasNext()) {
Map.Entry<String, Integer> next = it.next();
if (next.getValue() < minimum.getValue()) {
minimum = next;
}
}
return minimum.getKey();
}
return ""; // Inner map doesn't exist
}
Results:
Orange
If Java 8 is a option for you, it is easy to write a very concise method to do that:
public static String lowestValueKey(Map<String, Map<String, Integer>> map, String key) {
return map.get(key).entrySet().stream()
.min(Comparator.comparing(Map.Entry::getValue))
.get().getKey();
}
Also using Maps inside Maps can be very tedious sometimes. You may consider using Table<String, String, Integer> from Guava library.
Get the Hashmap from the inner hashmap and sort the hashmap based on the value which is shown in the link enter link description here. Obviously firs entry will be the lowest value in your innerhashmap.
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.
I am using a Javascript object as an object with configuration properties.
E.g. I have this object in javascript:
var myProps = {prop1: 'prop1', prop2: 'prop2', 'prop3': 'prop3'};
This object (NativeObject) is returned to me in Java function.
E.g.
public Static void jsStaticFunction_test(NativeObject obj) {
//work with object here
}
I want to get all properties from object and build HashMap from it.
Any help will be appreciated.
So, I solved my problem :)
Code:
public static void jsStaticFunction_test(NativeObject obj) {
HashMap<String, String> mapParams = new HashMap<String, String>();
if(obj != null) {
Object[] propIds = NativeObject.getPropertyIds(obj);
for(Object propId: propIds) {
String key = propId.toString();
String value = NativeObject.getProperty(obj, key).toString();
mapParams.put(key, value);
}
}
//work with mapParams next..
}
well, if you looked closer, you would have seen that NativeObject implements the Map interface, so you could have worked very well with the NativeObject.... But to answer your question: you could have used the common approach for getting the key-value pairs of any map
for (Entry<Object, Object> e : obj.entrySet()){
mapParams.put(e.getKey().toString(), e.getValue().toString());
}
A cast would have been enough for your case, because you have only strings as values. So, if you really wanted a HashMap:
HashMap<String, String> mapParams = new HashMap<String, String>((Map<String,String>)obj); //if you wanted a HashMap
But if you just wanted a generic Map, it was even simpler, and less RAM consuming:
Map<String, String> mapParams = (Map<String,String>)obj;