I'm trying to create a TreeMap which is capable of storing multiple beans(Row) mapped to one key. My current declaration of the TreeMap is :
Map<String, List<Row>> rowmap = new TreeMap<String, List<Row>>();
With this kind of declaration i can easily use this method to add :
rowmap.get(combinedKey).add(rowlst);
This was working well in my local machine. The problem due to some issue in the Live Tomcat server, I couldn't use the declaration mentioned above to declare the Map, it throws these errors :
Syntax error on token "<", ( expected
Syntax error, insert ")" to complete Expression
Syntax error on token "<", ( expected
Syntax error on token "(", invalid Expression
So I declared this way :
Map rowmap = new TreeMap();
this solves the previous error but i couldn't use rowmap.get(combinedKey).add(rowlst); to add multiple values to a key because .add is defined in List not TreeMap, from my understanding i need declare the TreeMap this way : Map<String, List<Row>> rowmap = new TreeMap<String, List<Row>>(); to be able to use rowmap.get(combinedKey).add(rowlst);.
It would be great if anyone could suggest a workaround to solve this problem. I'm open to all suggestion.Thanks a lot!
EDIT :
Tomcat version : 5.5.9
Java version : 1.6.0_41-b02
Instead of add method use put for Maps.
put(K key, V value) for example: rowmap.put(combinedKey,rowlst);
Related
I want to loop over the MultiMap in Freemarker template and access(display) the key and its distinct values(which are objects in this case):
Here TaskType is a String (dont misunderstand)
multiMap.put(TaskType.DHOLDING_TASK,Obj1);
multiMap.put(TaskType.BTRADE_TASK,Obj2);
multiMap.put(TaskType.ANONE,Obj3);
multiMap.put(TaskType.DHOLDING_TASK,Obj4);
multiMap.put(TaskType.CPRICE_TASK,Obj5);
multiMap.put(TaskType.BTRADE_TASK,Obj6);
multiMap.put(TaskType.ANONE,Obj7);
multiMap.put(TaskType.CPRICE_TASK,Obj8);
The output will look like this of teh MultiMap:
{CPRICE_TASK=[Obj5, Obj8], ANONE=[Obj3, Obj7], BTRADE_TASK=[Obj2, Obj6], DHOLDING_TASK=[Obj1, Obj4]}
My freeMarker code :
<#assign taskKeys = multiMap?keys >
<#list taskKeys as key>
${key} --It works fine till here :-)
`taskList[key] or taskList[key_values]---XXX both gives exception
How to display the multivalues associated with the key here in list???
I need to access the value part o fthe pair here(i.e. the RHS) : CPRICE_TASK=[Obj5, Obj8]
A help is much appreciated :)
Thanks ddekany for the reply.. :)
However, I could find the answer, It was mistake in freemarker code..I iterate over the keys as
<#list taskList?keys as taskType>
which is fine ..After that I should be iterating over the list associated with the key (i.e the multiple values)as it is a google multimap.Like:
<#assign values = taskList?values>
<#list values[taskType_index] as task>
I guess I was missing the assign tag in my code..while accessing the values of the keys.
Hope this will help some one.
I'm using java GAE server. I store List on my entity (as strings are very limited in length in GAE). I send Map to the client through the Endpoint, and I put this list under some key. Then I retrieve this list on Android client - and I get classcast exception. It appears that HashMap< String, Object > sent from GAE server is seen as JsonMap on Client. Whatever. I proceed, I retrieve my List... and how surprised I was to find out that on the client I got List< ArrayMap >, and on this ArrayMap, my Text is under the key named "value".
There is even more. Under one of the keys in the JsonMap, I had a null value. I retrieve it... and it appears as Object (which is not null). Calling toString on this object gives me some crappy string...
Could anyone tell me why these things are happening? Sure, I can just accept how it, but its strange and not logical, and undocumented... Why my List< Text > magically converts into List< ArrayMap >? How likely is that it varies with, lets say, Android version, or, I don't know, with weather outdoor?... Anyone could help me understand these situations? Or point me some relevant documentation / articles?
Example server-side:
#ApiMethod(name = "retrievePlayer")
public Map<String, Object> retrievePlayer(Map<String, Object> data, User user) throws Exception, OAuthRequestException, IOException {
Map<String, Object> result = new HashMap<String, Object>();
List<Text> list = new ArrayList<Text>();
list.add(new Text("something"));
result.put("myList", list);
result.put("myNull", null);
return result;
}
On the client side, the "result" is of type JsonMap. The "myList" is of type ArrayList (ok). myList.get(0) is of type ArrayMap, and its one-element ArrayMap - the element inside this map has key named "value", and a value of "something". The "myNull" is of type Object and is not null, its toString() method shows something like [Ljava.lang.Object;#1db9742.
I resolved the issues by returning empty string instead of null. For the List< Text >, I iterate through it on and add all the Texts as Strings to new List< String >, and then return this new list (but it costs cpu usage on the server)... I thought it will work more predictably and out-of-the-box.
In this particular example, the method will return an instance of Map<< String, Object>>. If you try to call this endpoint using https://your_app_id.appspot.com/_ah/api/explorer, the json return will be
{ "myList" : { { "value": "something"} }, "myNull" : null }.
The returned json seems to be correct and a null is returned for "myNull". The reason you are getting an instance of Object and not null is because of the handling of JSON null by the JSON library. Please check this link for more explanation (JSON null section).
As for why the List<< Text>> magically converts into List<< ArrayMap>>, this is because you define the return as an instance of Map<< String, Object>> and the returned json does not contain any type information. I think when converting to client objects the type information is obtained from the generated client code which is based on the signature of the ApiMethod.
I want to iterate a List nested in a Map, the data structure is like:
Map<Integer, List<Integer>> groups = new TreeMap<>()
// Some code else to put values into groups ...
Freemarker template:
<#list groups?keys as groupKey>
${groupKey} // It's OK here.
<#list groups[groupKey] as item> // Exception threw here, detail message is pasted below
${item}
</#list>
</#list>
Detail exception message:
FreeMarker template error:
For "...[...]" left-hand operand: Expected a sequence or string or something automatically convertible to string (number, date or boolean), but this evaluated to an extended_hash (wrapper: f.t.SimpleHash):
==> groups
So, what is the problem?
P.S.
I have tried groups.get(groupKey) instead of groups[groupKey], it throws a new Exception stack:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
java.lang.String.compareTo(String.java:108)
java.util.TreeMap.getEntry(TreeMap.java:346)
java.util.TreeMap.get(TreeMap.java:273)
freemarker.template.SimpleHash.get(SimpleHash.java:160)
freemarker.core.Dot._eval(Dot.java:40)
freemarker.core.Expression.eval(Expression.java:76)
The problem in the original question is that FTL's hash type is not like Map. It's a collection of "variables", that is, the keys must be String-s. (Even that ?keys works is a glitch in BeansWrapper... though now it comes handy.) Since the key is a number, FTL assumes that you want to get an item from a sequence (a List or array), or that you want to get a character from a string, hence the original error message.
The solution is using the Java API-s, like get in Dev-an's answer. (On the long term FTL meant to introduce the map type, so all this problems with non-string keys will end, but who knows when that will be...)
Update: Since 2.3.22 there's ?api to access the Java API of objects, like myMap?api.get(nonStringKey). However, it's by default not allowed (see the api_builtin_enabled configuration setting and more in the Manual: http://freemarker.org/docs/ref_builtins_expert.html#ref_buitin_api_and_has_api). Also note that as Java maps are particular about the numerical type, if the key is not an Integer coming from a Java, you have to use myMap?api.get(myNumericalKey?int).
Try the following:
<#list groups?keys as groupKey>
${groupKey}
<#list groups.get(groupKey) as item>
${item}
</#list>
</#list>
I am currently storing marshalling libraries for different client versions in a HashMap.
The libs are loaded using the org.reflections API. For simplicity sake I'll just insert a few values here by hand. They are unordered by intent, because I have no influence on in which order the map is initialized on start-up by the reflections API.
The keys (ClientVersion) are enums.
HashMap<ClientVersion, IMarshalLib> MAP = new HashMap<>();
MAP.put(ClientVersion.V100, new MarshalLib100());
MAP.put(ClientVersion.V110, new MarshalLib110());
MAP.put(ClientVersion.V102, new MarshalLib102());
MAP.put(ClientVersion.V101, new MarshalLib101());
MAP.put(ClientVersion.V150, new MarshalLib150());
All and well so far, the problem now is, that there are client versions out there where the marshalling did not change since the previous version.
Let's say, we have a client version ClientVersion.V140. In this particular case I am looking for MarshalLib110, assigned to ClientVersion.V110.
How would I get the desired result (without iterating through all entries and grabbing "the next lower" value each time)?
Thanks in advance!
How would I get the desired result (without iterating through all entries and grabbing "the next lower" value each time)
There is nothing you can do about "iterating through all entries" part: since the map is unordered, there is no way of finding the next smaller item without iterating the entire set of keys.
However, there is something you can do about the "each time" part: if you make a copy of this map into a TreeMap, you would be able to look up the next smaller item by calling the floorEntry method.
Another alternative is to copy the keys into an array on the side, sort the array, and run a binary search each time that you need to look up the next smaller key. With the key in hand, you can look up the entry in your hash map.
I recommend you to use NavigableSet. Look at this example:
HashMap<Integer, String> map = new HashMap<>();
map.put(100, "MarshalLib100");
map.put(110, "MarshalLib110");
map.put(102, "MarshalLib102");
map.put(101, "MarshalLib101");
map.put(150, "MarshalLib150");
NavigableSet<Integer> set = new TreeSet<>(map.keySet());
Integer key = set.lower(150); // ^ -> 110
String val = map.get(key); // ^ -> MarshalLib110
// or
key = set.higher(110);// ^ -> 150
val = map.get(key); // ^ -> MarshalLib150
Update: Using TreeMap to find next lower key is not really correct. Example:
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
treeMap.put(100, "MarshalLib100");
treeMap.put(110, "MarshalLib110");
treeMap.put(102, "MarshalLib102");
treeMap.put(101, "MarshalLib101");
treeMap.put(150, "MarshalLib150");
System.out.println(treeMap.floorKey(102));
System.out.println(treeMap.floorEntry(102));
System.out.println(treeMap.ceilingKey(102));
System.out.println(treeMap.ceilingEntry(102));
Output:
102
102=MarshalLib102
102
102=MarshalLib102
I have a plain hashmap with numeric values and would like to retrieve its content, ideally in a list (but that can be worked out).
Can it be done?
Try this:
library(rJava)
.jinit()
# create a hash map
hm<-.jnew("java/util/HashMap")
# using jrcall instead of jcall, since jrcall uses reflection to get types
.jrcall(hm,"put","one", "1")
.jrcall(hm,"put","two","2")
.jrcall(hm,"put","three", "3")
# convert to R list
keySet<-.jrcall(hm,"keySet")
an_iter<-.jrcall(keySet,"iterator")
aList <- list()
while(.jrcall(an_iter,"hasNext")){
key <- .jrcall(an_iter,"next");
aList[[key]] <- .jrcall(hm,"get",key)
}
Note that using .jrcall is less efficient than .jcall. But for the life of me I can not get the method signature right with .jcall. I wonder if it has something to do with the lack of generics.
I have never done this myself, but there is an example in the rJava documentation of creating and working with a HashMap using the with function:
HashMap <- J("java.util.HashMap")
with( HashMap, new( SimpleEntry, "key", "value" ) )
with( HashMap, SimpleEntry )