I get bellow exception from my java codes.
java.lang.ClassCastException: scala.collection.immutable.Map$Map1 cannot be cast to java.util.HashMap
at au.com.vroc.udf.medianUDF.update(medianUDF.java:79)
I am getting error in my spark application when I cast the buffer to HashMap of java.utill. This is my codes:
public void update(MutableAggregationBuffer buffer, Row input) {
if (!input.isNullAt(0)) {
HashMap currentBuffer=(HashMap) buffer.get(0);//getting exception here
//HashMap currentBuffer=new HashMap();
currentBuffer.put(input.getLong(0), input.getDouble(0));
//currentBuffer.add(currentMap);
buffer.update(0, currentBuffer);
}
}
I guess instead of java hashmap I have to use "scala.collection.immutable.Map$Map1" inside my java class. Can I use any tool in "JavaConversions" namespace.
Anyhep would be appreciated!
Simplest approach would likely be to use Scala Converters.
It should look something like this (not tested, but type-checks):
import scala.collections.JavaConverters
java.util.Map currentBuffer = JavaConverters.mapAsJavaMapConverter(buffer.get(0)).asJava();
Please note that it returns type-parameterized map (i.e. java.util.Map<K, V>), not the non-parameterized java.util.HashMapin your example - you might want to alter the rest of your code to work on the parameterized maps for better type safety.
You get java.util.Map you should use getJavaMap method:
java.util.Map<T, U> currentBuffer = (java.util.Map<T, U>) first.getJavaMap(0)
Note that this is not HashMap - initialized value is Encoded on update and decoded on get. To modify it, you have to make a copy.
Related
I am using Apache Ignite, which isn't really central to the question, but gives background. In that context, I've create a class extending CacheStoreAdapter that has a method with the following signature:
#Override
public void write(Entry<? extends K, ? extends V> cacheEntry) throws CacheWriterException {
I registered that class with Ignite, so that it calls the write() method whenever I give it data to save in its cache.
What I was surprised to find is that, depending on how Ignite is otherwise configured, the following code...
final V cacheObject = cacheEntry.getValue();
LOG.info("cacheObject = " + ToStringBuilder.reflectionToString(cacheObject));
... outputs the following:
cacheObject = org.apache.ignite.internal.binary.BinaryObjectImpl#7c40ffef[ctx=org.apac
That is, the cacheObject taken from an Entry<? extends K, ? extends V> is not an instance of type V!
I've worked around the issue (as I said it only happens depending on how Ignite is otherwise configured), but I am curious how this is even done in Java.
TL;DR Question:
How is is possible to pass a variable to a method that does not conform to the method's signature? Some kind of reflection technique? Is there a common / legitimate use for doing this?
In java, type parameters are optional: they are not carried along with an object instance and only exist on language level.
So you can always cast anything to and then call any methods with type checks erased:
Map<String, Integer> sim = new HashMap<>();
Map<Object, Object> oom = (Map<Object, Object>) (Map) sim;
As for BinaryObjectImpl, Ignite will try to keep objects in serialized state where possible to save on serialization costs. So you should be aware that type parameters of CacheStore are not always the user-facing types.
It is possible that the caller to your implementation of write creates an instance of the raw type Map.Entry. For example:
Entry entry = new Entry() { /* ... */ }
...
cache.write(entry);
Having read the documentation on "Inline Maps" for Spring Expression Language, I am passing an object to a SpelExpressionParser and .toString()ing the Object, so to speak; however, in doing so, I am receiving the following error:
org.springframework.expression.spel.standard.SpelExpression cannot be
cast to java.util.Map
The Object passed to as the argument to the .parseExpression function is the result of the annotation #PreAuthorize("hasPermission(#object, {name: 'roofus', animal: 'dog'}) "affixed" to a method.
Through the PermissionEvaluator interface implementation, it is passed in its Object form to a method:
private boolean doSomething (Object animal) { //....
Within this method is found an #Autowired SpelExpressionEvaluator. This is used in the following way:
Map animalMap = (Map) parser.parseExpression(animal.toString());
Through debugging, I know that the .toString() method results in: {name=roofus, animal=dog}
Resulting in the aforementioned error. Am I missing something? The goal is to be able to pass in a "JSON"-esque String (as specified by the linked documentation) for evaluation purposes.
Your problem that parser.parseExpression can't return Map independently of circumstances .
Looks like you misunderstood the architecture a bit. The SpelParser is for building Expression object from the the String. After that you can evaluate that expression using one of its getValue() method.
So, only after the evaluation you can get your Map object:
Expression expression = parser.parseExpression("{name: 'roofus', animal: 'dog'}");
Map map = expression.getValue(Map.class);
animal is already a Map (notice the formatting in the OP of the .toString() result) and not in the correct format expected by the parser. In this case, you don't even need the parser if the objective is to retrieve information from the Map:
((Map<String, String>)animal).get("animal")
So, in response to the solution proposed by Artem Bilan, this would actually work:
Map animalMap = (Map) parser.parseExpression("{name: 'roofus', animal: 'dog'}").getValue();
However, again, what is actually received (and the cause of the problem in the OP) is: parser.parseExpression("{name=roofus, animal=dog}")
I have a very simple Jackson code to deserialize a nested JSON object:
public class MapTest
{
public static void main(String ... args) throws Exception
{
final String ser = "{\"nested\":{\"k1\":\"v1\",\"k2\":\"v2\",\"k3\":\"v3\"}}";
final Map<String, Object> deser = new ObjectMapper().readValue(ser, new TypeReference<TreeMap<String, Object>>(){});
System.out.println("Class of deser's nested object is " + deser.get("nested").getClass().getSimpleName());
}
}
When I run this I obtain the following output:
Class of deser's nested object is LinkedHashMap
However I want the nested map to be deserialized as a TreeMap rather than as a LinkedHashMap as per the output. How can I tell Jackson to default to use a TreeMap when deserializing?
Reading through the documentation the closest thing I found was the ability to define concrete classes for abstract types through addAbstractTypeMapping() in a module but I've tried every superclass and instance of LinkedHashMap in an attempt to do this and nothing seems to work.
This is using Jackson 2.4.2, although if there is a way to do this that requires a higher version I would be able to upgrade.
Module's addAbstractTypeMapping() is indeed the way to achive mapping in general. But the problem may be due to recursive nature of deserialization; because inner values are considered to be of type java.lang.Object.
However, I think there were indeed fixes to this part in 2.5, so I would specifically checking to see if 2.5.0 would work, once you add abstract mapping from Map to TreeMap.
If this does not work, please file a bug at https://github.com/FasterXML/jackson-databind/issues since it should work.
Here's the code snippet I'd like to translate from Java to C#. I'm not sure what's causing the error but I've never used ArrayLists and vectors before. Thanks in advance!!
//Java class definitions, constructors, fields, methods etc here.
//sphbasis is a Vector object.
public SphericalHarmonicDecomposition[] getSphericalHarmonicBasis() {
return (SphericalHarmonicDecomposition[])(sphbasislist.toArray(
new SphericalHarmonicDecomposition[sphbasislist.size()]));
}
I've tried doing the following in C#:
//C# class definitions, constructors, fields, methods etc here.
//sphbasis is a ArrayList object.
public SphericalHarmonicDecomposition[] getSphericalHarmonicBasis() {
return (SphericalHarmonicDecomposition[])(sphbasislist.ToArray(
new SphericalHarmonicDecomposition[sphbasislist.Count]));
}
I get the following errors. I'm using Mono and Xamarin studio on a mac.
Error CS1502: The best overloaded method match for
`System.Collections.ArrayList.ToArray(System.Type)'
has some invalid arguments (CS1502) (projectx)
and
Error CS1503: Argument `#1' cannot convert
`matdcal.engine.model.SphericalHarmonicDecomposition[]' expression
to type `System.Type' (CS1503) (projectx)
Please try the following. In Java you need to pass an array to the toArray method, but that's not correct in C# (.NET).
//C# class definitions, constructors, fields, methods etc here.
//sphbasis is a ArrayList object.
public SphericalHarmonicDecomposition[] getSphericalHarmonicBasis() {
return (SphericalHarmonicDecomposition[])(sphbasislist.ToArray());
}
References
Java ArrayList.toArray
C# List.ToArray
I'm looking for the alternatives to serialize objects in my Android project. I found Wobly which seem to be fast and small. I understand how to create Wobly wrappers using WoblyImpl but I'm totally confused with how to write/read these objects from the file system? When to run WoblyGenerator and can it be done within my code? Can someone post a code example?
Wobly doesn't support unknown Object fields. So fields like:
Object a;
List<Object> b;
Map<Integer, Object> c;
cannot be serialized with Wobly.
It supports all primitive classes (and their boxed counterparts), all Wobly classes, any Array/List/Map combination of the above.
So in your case, problem is that JSONArray implements List<Object>. If you know what kind of object JSONArray holds, for example List<Map<Integer, String>>, you can write:
class Example extends WoblyImpl {
#WoblyField(id = 0)
List<Map<Integer, String>> array;
public void setArray(JSONArray json) {
array = (List)json;
}
}
Though after deserialization you will get ArrayList<HashMap<Integer,String>> and not JSONArray back.
If you don't know what object JSONArray is holding, it would be painful to make it work with Wobly, if at all possible. You can check out comprehensive comparison of serialization libraries here:
https://github.com/eishay/jvm-serializers/wiki
OK, I got it. If you wondered here and want to know how to do it here are the steps:
Create your class by extending WoblyImpl and annotate the fields according to the instructions
Then run WoblyGenerator.updateSourceFolder("c:/foo/src"); where the parameter is directory containing your file (or package). I created a small project in Eclipse for that but you can also run this from the command line using supplied wobly-generator.jar
This step will inject serialization code into your source file which will include read and write methods
Gotcha: this didn't work for smart-json JSONObject or JSONArray or for HashMap. The error I got is this:
java.lang.IllegalArgumentException: next type for class net.minidev.json.JSONObject of index 0, class java.lang.Class
at com.wowd.wobly.generation.WoblyGeneratorUtils.extractNextType(WoblyGeneratorUtils.java:91)
at com.wowd.wobly.generation.types.impl.MapTypeCodeGenerator.defaultTypeFormat(MapTypeCodeGenerator.java:163)
at com.wowd.wobly.generation.types.TypeCodeHandler.defaultTypeFormat(TypeCodeHandler.java:121)
at com.wowd.wobly.generation.WoblyGeneratorUtils.adjusFormatForCompressed(WoblyGeneratorUtils.java:317)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateWriteFieldCode(WoblyCodeGenerator.java:178)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateWriteMethod(WoblyCodeGenerator.java:270)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateFieldsAndMethods(WoblyCodeGenerator.java:647)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateRegularCode(WoblyCodeGenerator.java:721)
at com.wowd.wobly.generation.WoblyCodeGenerator.generateCode(WoblyCodeGenerator.java:677)
at com.wowd.wobly.updater.GenerateAndReplace.update(GenerateAndReplace.java:130)
at com.wowd.wobly.updater.GenerateAndReplace$1.execute(GenerateAndReplace.java:198)
at com.wowd.wobly.updater.GenerateAndReplace$1.execute(GenerateAndReplace.java:1)
at com.wowd.common.functions.impl.FilterProcedure.execute(FilterProcedure.java:40)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:69)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:60)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:60)
at com.wowd.wobly.updater.SourceFilesVisitor.visitDir(SourceFilesVisitor.java:60)
at com.wowd.wobly.updater.SourceFilesVisitor.visitPackage(SourceFilesVisitor.java:38)
at com.wowd.wobly.updater.GenerateAndReplace.updateInPackage(GenerateAndReplace.java:190) WoblyParcel error
at com.wowd.wobly.WoblyGenerator.updatePackage(WoblyGenerator.java:60)
at com.wowd.wobly.WoblyGenerator.updateSourceFolder(WoblyGenerator.java:49)
at Generator.main(Generator.java:19)
If someone can tell me how to fix that - post it as a separate answer and I'll accept it