Unable to Cast Map into Java Class - java

public class Model extends LinkedHashMap<String, Object>{
}
LinkedHashMap<String, Object> map = //instance of LinkedHashMap
Model model = (Model) map // Exception.
when I'm trying to cast LinkedHashMap<String,Object> into my Model class I'm getting class cast exception.
I'm basically using user defined method which expect Model as an argument that's why I'm casting my map into Model class

You cannot do that because Model is not an instanceof LinkedHashMap. Think in terms of memory allocation. What have you actually done? You have allocated enough memory for a LinkedHashMap but NOT for a Model. The compiler is trying to save you from yourself.

You cannot use LinkedHashMap where Model is expected, therefore you cannot cast.
Presumably Model has additional methods and more functionality than LinkedHashMap. Even if you did not add anything new in Model class yet, Java assumes that you will.
Possible solution: change
LinkedHashMap<String, Object> map = //instance of LinkedHashMap
to
LinkedHashMap<String, Object> map = //instance of Model
Another solution: change the code that uses Model class to use Map instead.
Still another approach: do not derive Model from Map, have Model own a Map. Change the code accordingly.
In general, you need to learn more about OO programming, especially the modern sort that deprecates inheritance in favor of aggregation.

API Specifications for the ClassCastException says:
Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance.
class P {
}
class C extends P {
}
P p = new P();
C c = (C) p;//java.lang.ClassCastException; Runtime Exception
If you really want to do it. You do it in this way:
LinkedHashMap map = new Model();
map.put("one", "1");
Model model = (Model) map; // Exception.
System.out.println(model);
referece: Explanation of "ClassCastException" in Java

Related

More succinct way of creating a constant String map in Java

Good day all,
Considering the following code example:
import java.util.HashMap;
import java.util.Map;
public class StaticPractice {
private final Map<String, String> mapperMap;
public StaticPractice(){
mapperMap = new HashMap<String, String>();
mapperMap.put("Foo1", "Bar1");
mapperMap.put("Foo2", "Bar1");
mapperMap.put("Foo3", "Bar2");
mapperMap.put("Foo3", "Bar3");
//...
mapperMap.put("MoreFoo", "BarAgain");
}
public void doSomething(){
//use mapperMap
}
}
I am looking for a more succinct way of creating a Map data structure that has a whole lot of constant Strings mapping to a whole lot of other constant Strings. In use, the example is far from "clean" or elegant, and is very verbose (there are alot of predefined constant mappings).
The goal of the class is to map objects referenced by these predefined constant Strings. It is commonplace in my particular code convention to use private static final String for all String constant, this example as well breaks that convention.
Would greatly appreciate any input, the wealth of knowledge from SO contributors always humbles me.
Much thanks.
Edit: Requirement specifies no external files.
One approach would be to create a builder class that generates the map. This has the advantage that you can optimize for concise syntax. You can also do things like making the generated map immutable -- useful if you want to use it as a publically accessible constant.
In your example, I notice that you have more than one key mapping to the same value. So, it would be more concise to have a method that takes a value followed by a list of keys. You can also make it more concise by having the builder return itself so that you can "chain" method calls:
class Builder<K,V> {
final Map<K,V> map = new HashMap<K,V>();
Builder add(V value, K... keys) {
for(K key : keys) {
map.put(key, value);
}
return this;
}
Map<K,V> build() {
return Collections.unmodifiableMap(new HashMap<K,V>(map));
}
}
// Usage:
mapperMap = new Builder<String,String>()
.add("Bar1", "Foo1", "Foo2")
.add("Bar2", "Foo3")
...
.build();
Alternately you might take a look at the Guava ImmutableMap class, which has a builder using the chaining syntax, though it doesn't have a way to map multiple keys to a single value in one call.
I Think you can try using Properties instead of map or initializing the map by reading strings from a configration file.
The most succint way I know is to define your map as an anonymous subclass of HashMap with an instance initializer:
private final Map<String, String> mapperMap =
Collections.unmodifiableMap(new HashMap() {{ // instance initializer
put("Foo1", "Bar1");
put("Foo2", "Bar1");
put("Foo3", "Bar2");
put("Foo3", "Bar3");
}});
If you want it to be a final String, you can always create a class with a couple of constant strings and the use a list of objects of that class.
You can do it like this:
class MapClass {
private static final String key;
private static final String value;
}
List<MapClass> l = new ArrayList<>();

How to clear out the contents of a map when clear() method call throws UnsupportedOperationException?

How can I empty a map contents if I keep getting an UnsupportedOperationException when I call clear() method on the map instance ?
You shouldn't. There is something wrong in the contracts of the collaborating objects and their methods. You expect a modifiable map, but get an unmodifiable view. You should redefine the contracts and/or adopt any of the implementations accordingly. If you are not in control of the one, who is passing you that map, then there is probably a reason for it passing you an unmodifiable view.
If the Map is an UnmodifiableMap (for instance, gotten from Collections.unmodifiableMap()), there's little you can (and should) do to modify it, except creating a new reference and clearing it.
Map unmodifiable = Collections.unmodifiableMap(m);
Map newMap = new HashMap(unmodifiable);
newMap.clear();
unmodifiable = newMap;
That said, it is actually possible to modify an UnmodifiableMap. It turns out that Collections.UnmodifiableMap is nothing more than a class implementing the Map interface, and wrapping the actual Map. It delegates on the wrapped Map for its read-only methods, and throws UnsupportedOperationExceptions in its implementations of methods that alter the map. It is possible to get the wrapped Map by reflection, and therefore modify it.
DISCLAIMER: Take into account that this must be used with extreme caution. If the unmodifiable map is provided by a a library or similar, it might be making assumptions about its nature, and violateing its contract can lead to unexpected/undesirable results. Also, this might be relying on internals that might be changed without notice or differ between versions.
// Creates a standard map
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("1", "a");
myMap.put("2", "b");
// Creates an unmodifiableMap. Actually a wrapper for myMap.
Map unmodifiableMap = Collections.unmodifiableMap(myMap);
System.out.println("Size of unmodifiable map is: " + unmodifiableMap.size());
try{
// Get classes declared in java.util.Collections
Class[] classes = Collections.class.getDeclaredClasses();
for(Class cl : classes) {
// Look for the UnmodifiableMap class
if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
// The wrapped Map is in an attribute called "m"
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
// Get the wrapped map
Object obj = field.get(unmodifiableMap);
Map map = (Map) obj;
// modify it
map.clear();
}
}
}
catch (Exception e){ System.out.println(); }
System.out.println("Size of unmodifiable map is: " + unmodifiableMap.size());
(credit to this blog post)

HashMap<String, Object> : How to put Object itself as in place of String

A a = new A(); //classA { }
HashMap<String, Object> hm = new Hashmap<String,Object>();
hm.put("A", a);
My question is, How can i put the Object itself instead of "A" in same declaration?
hm.put(`a??`, a);
You simply cannot do that, the language prohibits it. It would only be possible if your class A is a subclass of String which is not possible, since String is declared as final in Java.
With respect to you interview question: It's not possible due to the generic type parameter that was chosen for the declaration. You can read more about that in Bounded Type Parameters.
A a = new A(); //classA { }
Map<A, A> hm = new Hashmap<A, A>();
hm.put(a, a);
But I do not see any point of putting a->a
If the class held a non-changing decent String field, you could use that.
// the id property must be a String, immutable and unique for each instance!
myMap.put(a.getId(), a);
If you want to make any object as a key in your HashMap, then that object has to be immutable.. Because, you don't want anyone to change your key, after you add them to your HashMap..
Just imagine, if your keys are changed after insertion, you won't ever be able to find your inserted value..
But if your key is immutable, then if anyone tries to change your keys, he will actually create a new one for himself, but you will still have yours..
That is what happens in case you use String as your key in HashMap(They can't be changed).. So, if you want your object to be a key, either you make your class a subclass of String (that you can't do), or, just make your class immutable..
This is actually possible using a raw type, like this:
Object key = ...;
Object value = ...;
Map<String, Integer> map = new HashMap<>();//a normal map
Map rawMap = map; // here is the raw type
rawMap.put(key, value); // it works!
This runs fine, but problems arise when you try to use the generic map later:
Integer value = map.get(key);// ClassCastException (unless value actually is an Integer)
That's why you were told that it's a "dirty trick". You shouldn't use it.

Creating instance list of different objects

I'm tring to create an arraylist of different class instances. How can I create a list without defining a class type? (<Employee>)
List<Employee> employees = new ArrayList<Employee>();
employees.add(new Employee());
Employee employee = employees.get(0);
You could create a list of Object like List<Object> list = new ArrayList<Object>(). As all classes implementation extends implicit or explicit from java.lang.Object class, this list can hold any object, including instances of Employee, Integer, String etc.
When you retrieve an element from this list, you will be retrieving an Object and no longer an Employee, meaning you need to perform a explicit cast in this case as follows:
List<Object> list = new ArrayList<Object>();
list.add("String");
list.add(Integer.valueOf(1));
list.add(new Employee());
Object retrievedObject = list.get(2);
Employee employee = (Employee)list.get(2); // explicit cast
List<Object> objects = new ArrayList<Object>();
objects list will accept any of the Object
You could design like as follows
public class BaseEmployee{/* stuffs */}
public class RegularEmployee extends BaseEmployee{/* stuffs */}
public class Contractors extends BaseEmployee{/* stuffs */}
and in list
List<? extends BaseEmployee> employeeList = new ArrayList<? extends BaseEmployee>();
List anyObject = new ArrayList();
or
List<Object> anyObject = new ArrayList<Object>();
now anyObject can hold objects of any type.
use instanceof to know what kind of object it is.
I believe your best shot is to declare the list as a list of objects:
List<Object> anything = new ArrayList<Object>();
Then you can put whatever you want in it, like:
anything.add(new Employee(..))
Evidently, you will not be able to read anything out of the list without a proper casting:
Employee mike = (Employee) anything.get(0);
I would discourage the use of raw types like:
List anything = new ArrayList()
Since the whole purpose of generics is precisely to avoid them, in the future Java may no longer suport raw types, the raw types are considered legacy and once you use a raw type you are not allowed to use generics at all in a given reference. For instance, take a look a this another question: Combining Raw Types and Generic Methods
How can I create a list without defining a class type? (<Employee>)
If I'm reading this correctly, you just want to avoid having to specify the type, correct?
In Java 7, you can do
List<Employee> list = new ArrayList<>();
but any of the other alternatives being discussed are just going to sacrifice type safety.
If you can't be more specific than Object with your instances, then use:
List<Object> employees = new ArrayList<Object>();
Otherwise be as specific as you can:
List<? extends SpecificType> employees = new ArrayList<? extends SpecificType>();
I see that all of the answers suggest using a list filled with Object classes and then explicitly casting the desired class, and I personally don't like that kind of approach.
What works better for me is to create an interface which contains methods for retrieving or storing data from/to certain classes I want to put in a list. Have those classes implement that new interface, add the methods from the interface into them and then you can fill the list with interface objects - List<NewInterface> newInterfaceList = new ArrayList<>() thus being able to extract the desired data from the objects in a list without having the need to explicitly cast anything.
You can also put a comparator in the interface if you need to sort the list.
I know this is an old question, but there's a nice and easy way to do this (it works with the mostly recent versions of ElasticSearch Rest API).
The search object goes like:
SearchResponse<JsonData> search = client.search(s -> s
.index(index)
.query(query),
JsonData.class);
And then I iterate over the response like this:
for (Hit<JsonData> hit: search.hits().hits()) {
String stringSource = hit.source().toString();
MySavedRegister mySavedRegister = mapper.readValue(stringSource, mySavedRegister .class);
mylist.add(esGenericEvent);
}
Where mySavedRegister stands for the class that has the hits' sources parameters.

How to use a custom class as a type variable for an Iterator?

I have the following code using generics:
Set membersKeySet = membersList.keySet();
Iterator<DoubleKey> membersItr = membersKeySet.iterator();
while(membersItr.hasNext()){
DoubleKey<Integer, Integer> dk = membersItr.next();
}
Eclipse tells me that "Set is a raw type. References to generic type <E> should be parametrized". DoubleKey is also a Generic class. What I understand is that the .iterator() method doesn't assure that the DoubleKey Class has been passed with the same parameter types. I tried typecasting but it doesn't work. How can I pull this off? Thanks!
P.S. I'm still n00b inusing Generics.
If the objects stored in the set are instances of DoubleKey<Integer, Integer>, then the code should look like this :
Set<DoubleKey<Integer, Integer>> membersKeySet = membersList.keySet();
Iterator<DoubleKey<Integer, Integer>> membersItr = membersKeySet.iterator();
while(membersItr.hasNext()){
DoubleKey<Integer, Integer> dk = membersItr.next();
}
You should define type of the keyset.
Set<DoubleKey> membersKeySet = membersList.keySet();
Could you please provide memberList definition to provide the full picture?
Well depending on what membersList is, I'd expect this to be the solution:
Set<DoubleKey> membersKeySet = membersList.keySet();
If membersList is also declared using a raw type, it becomes trickier... but we'll cross that bridge when you've checked whether that's all you need :)
From the code you give, it looks like membersList is actually a map of some sort. So, in order to get the compile time type safety of generics, membersList should be defined appropriately, something like
Map<DoubleKey, Object> membersList = new HashMap<DoubleKey, Object>();
Set<DoubleKey> membersKeySet = membersList.keySet();
With that, your iterator should work as you have it.
Normally you'd use the compact for-loop notation:
while(DoubleKey<Integer, Integer> dk: membersList.keySet()) {
}
And if you are using DoubleKey<Integer, Integer> all over the place, consider making it a class all on its own:
class IIKey extends DoubleKey<Integer, Integer> {}

Categories