The following code throws a ClassCastException. The collection in question actually does hold ArrayList<String>.
HashMap listing = (HashMap) data.get(s);
Collection<ArrayList<String>> collection = listing.entrySet();
int count = 0;
for ( ArrayList al : collection ) // exception occurs here
{
count += al.size();
}
I am assuming that this must be converted to Object and
a) I can't seem to figure out how to convert from Object to ArrayList properly
b) I'm not even sure if thats the issue..
Perhaps someone can provide some insight?
Edit: HashMap listing is a HashMap<String, ArrayList<String>>
Your code has problem in second line
listing.entrySet() always return Set<MapEntry<Key,Value>>
That cannot be casted to Collection<ArrayList<String>> even though set is a subtype of collection because the generics are differ.
And then in the HashMap(listing) what is the type of key and value?
HashMap.entrySet() returns Set<Map.Entry<K,V>>. This is not compatible with Collection<ArrayList<String>>.
As a side note, your HashMap is a raw type and should be parameterized.
I think the most pluasible place where the exception is occuring is at the following line :
HashMap listing = (HashMap) data.get(s);
Are you sure data.get(s) is suppose to return hashmap.
Also entrySet returns a set that is incompatible incompatible to your assignment.
Related
I'm new at posting questions here, but have been looking since yesterday for a solution for this and couldn't find. Would really appreciate the help.
I have two lines, at which I'm trying to put generic elements inside a list and get a type mismatch for sending Long elements to List.
List<Long> returnedPages = m_algo.getElement(Arrays.asList(pageIds));
List<Long> pagesNotInRam = new ArrayList<>();
List<Long> pageIdsToHandle = m_algo.putElement(pagesNotInRam, pagesNotInRam);
m_algo is defined
private IAlgoCache<Long, Long> m_algo;
and IAlgoCache works with generic types
public interface IAlgoCache <K, V> {
public V getElement(K key);
public V putElement(K key, V value);}
Can I make this work? Should I work in some sort of loop?
There are several problems with your code. For example
public V getElement(K key); // takes an object as an argument (Long in your case)
m_algo.getElement(Arrays.asList(pageIds)); // you pass a list of objects (I suppose longs)
And even if you fix that issue and pass a proper key later you are trying to assign a Long object to a List. That's why it complains - assigning and object to a collection cannot be done because they are basically different types.
List<Long> returnedPages = m_algo.getElement( properKey ); // Problem
Try with:
List<Long> returnedPages=new ArrayList();
returnedPages.add(m_algo.getElement( properKey));
The problem with putElement is the same. You just need to distinguish between an object and an array or collection of objects. Even if they have the same type they are not interchangeable.
Is there a way to do this without the need to use #SuppressWarnings("unchecked")
if (o instanceof Map) {
Map<Object, Object> newMap = (Map<Object, Object>) o;
...
}
If you want to write to the map, the short answer is no. Well you can code it as in example given in the link mentioned by #brso05, but I think this is just defying the purpose. Basically the compiler tells you it cannot make sure types in the map are compatible.
If you don't have to write to that map you can use Map<?, ?>, which means that you can only get items of type Object from it. Like for example:
Map untypedMap = new HashMap();
Map<?, ?> map = untypedMap;
Object someValue = map.get(aKey);
Reasoning
The reason for that is that Java collections are not covariant.
Just for simplicity sake, let's talk about Lists (but it applies to Maps also).
The following is not valid in Java (and for a good reason):
List<Integer> integers = new ArrayList<Integer>();
List<Object> objects = integers; // illegal
Collections in Java are mutable, which means you could do something like this:
objects.add(1.4f);
This would alter the original integers list, and will ad a float to it. The float is an object so it typechecks against List<Object>.
Now because of backwards compatibility this kinds of assignments are possible, if a list is untyped. For example:
List untyped = new ArrayList();
List<Integer> integers = untyped; // warning here
integers.add(1);
List<Float> floats = untyped; // warning here
floats.add(1.4f);
So the code compiles, but is faulty. Consider following example.
System.out.println(untyped.get(0)); // is okay
System.out.println(untyped.get(1)); // is okay
Float aFloat = floats.get(0);// compiles, but throws ClassCastException
System.out.println(aFloat);
Integer anInteger = integers.get(1);// compiles, but ClassCastException
System.out.println(anInteger);
Because of above, whenever you assign an untyped collection to a typed collection, a compiler issues a warning.
I am a writing a class that whose constructor takes an List<String> and returns a hashmap having length of string as key(Integer) and its value as arrayList<String> that holds string.
That is I am trying to map length of strings to list of strings. Here is my code.
public class Solver {
Map<Integer,ArrayList<String>> inventoryMap;
//constructor
public Solver(List<String> list){
inventoryMap=new HashMap<Integer,ArrayList<String>>();
for (String s : list) {
int x = s.length();
if (inventoryMap.containsKey(x)){
inventoryMap.put(x,inventoryMap.get(x).add(s));
} else {
newlist=new ArrayList<String>();
newlist.add(s);
inventoryMap.put(x,newlist);
}
}
}
when I complile this code, I get the following error
Solver.java:12: put(java.lang.Integer,java.util.ArrayList<java.lang.String>) in java.util.Map<java.lang.Integer,java.util.ArrayList<java.lang.String>> cannot be applied to (int,boolean)
inventoryMap.put(x,inventoryMap.get(x).add(s));
I think I am going wrong in adding String elements to my ArrayList<String> which is value of Map
can you guide me with what I could possibly be going wrong?
if (inventoryMap.containsKey(x)) {
inventoryMap.put(x,inventoryMap.get(x).add(s));
}
Change this with
if (inventoryMap.containsKey(x)) {
inventoryMap.get(x).add(s);
}
Reason is inventoryMap.get(x).add(s) will return boolean so you cann't put boolean in place of List.
As map already contains list so adding any element in a list you need not to put any entry in a map. Just get the list from map and add element to it.
inventoryMap.get(x).add(s) returns boolean and you tried to put it in the map. This is the cause of the exception. Put the list in the map will resolve the issue.
Your code inventoryMap.get(x).add(s) adds the value to the list and return a boolean.
So You need to have something like.
List<String> list =inventoryMap.get(x);
list.add(s);
You cannot chain your method calls like inventoryMap.put(x,inventoryMap.get(x).add(s)) since add returns a boolean. As a matter of fact, you don't even need the put statement. Since you aren't removeing the List, its reference will stay in the Map so any updates to the List will be visible.
All you need is inventoryMap.get(x).add(s).
First of all inventoryMap.get(x).add(s) returns boolean(whether elements where successfully added or not ). So is incompatible with the type ArrayList<String>. You can simple do
inventoryMap.get(x).add(s)
No need to explicitly call pur() function.
Secondly int x = s.length(); should be Integer x = s.length();. You can put int where Integer is expected(anyways you cannot use int in generics).
The problem with this line
inventoryMap.put(x,inventoryMap.get(x).add(s));
is that inventoryMap.get(x).add(s) will return a boolean and map expects a List here. You need to break down this statement. something like this:
List<String> stirngsList = inventoryMap.get(x);
stirngsList.add(s);
I'm stuck trying to get something to work in an assignment. I have a HashMap<Integer, ArrayList<Object>> called sharedLocks and I want to check whether a certain value can be found in any ArrayList in the HashMap.
The following code obviously wouldn't work because Object[] can't be cast to ArrayList[], but it is a demonstration of the general functionality that I want.
ArrayList[] values = (ArrayList[]) sharedLocks.values().toArray();
boolean valueExists = false;
for (int i = 0; i < values.length; i++) {
if (values[i].contains(accessedObject)) {
valueExists = true;
}
}
Is there a way for me to check every ArrayList in the HashMap for a certain value? I'm not sure how to use the values method for HashMaps in this case.
Any help would be much appreciated.
HashMap.values() returns a Collection. You can iterate through the collection without having to convert it to an array (or list).
for (ArrayList<Object> value : sharedLocks.values()) {
...
}
A HashMap is a bit special, in that it doesn't really have an index to go by at all...
What you want to do, is turn the HashMap into a collection first, and then iterate through the collection with an iterator.
Whenever you get hold of an ArrayList in the HashMap, you cycle through every element in the arrayList, and then you jump out if you find it :)
Use the toArray method which takes an array as an argument.
This uses the array you specify to fill the data, and maintains the typing so you don't need to typecast. Additionally, you should keep the generic <Object> in the definition.
ArrayList<Object>[] values =
sharedLocks.values().toArray(new ArrayList<Object>[sharedLocks.size()]);
One more thing to consider is if multiple threads can modify this HashMap. In this case, you will want to synchronize this line of code to the HashMap and make sure all modifications are also synchronized. This will make sure that other threads won't modify the contents between the .size() call and the .toArray() call, which is possible.
You dont need arrays:
boolean valueExists = false;
for (ArrayList<Object> value : sharedLocks.values()) {
if (value.contains(accessedObject)) {
valueExists = true;
break;
}
}
Why not just iterate through all the values in the map:
for (ArrayList<Object> list : sharedLocks) {
if (list.contains(accessedObject)) {
// ...
}
}
heres a link to an example of iterating though a hash map. Use this to pull out each arraylist and in turn extend this to then search each element of the array list for the given entry.
http://www.java-examples.com/iterate-through-values-java-hashmap-example
you will need to use a nested foreach loop.
foreach(every element in the hashmap) {
foreach(every element in arraylist) {
// do comparision
}
}
you might just get away with a foreach loop and a keyExists() call or something within it. I cannot recall the API off the top of my head.
I'm not able to navigate down to the HashSets in my datastructure
I declared an array of Map[] and populated it with HashMap with K of Integer, and V of HashSet of String but was unable to add items to the HashSet.
I've trimmed the code down to illustrate ...
private Map[] myMaps = null;
myMaps = new Map[numRepeats];
myMaps[0] = new HashMap<Integer,HashSet<String>>();
myMaps[0].put(0, new HashSet<String>());
The popup in NetBeans shows I can get to java.util.Map with
myMaps[0].
but using the map.get(0) method I thought would return the HashSet
myMaps[0].get(0).
shows I've got to generic java.lang.object, not to the HashSet. Since I need to use the HashSet.add() method next this means I'm stuck. I would appreciate suggestions.
Thank you
You need to cast it to HashMap<Integer,HashSet<String>>.
When you define your map, you could define it with the full types involved, so:
private Map<Integer, HashSet<String>>[] myMaps = null;
Then, you wouldn't have to cast it back (assuming all your maps in myMaps will be of that type).
Unfortunately, Java Generics make it rather tricky to have an array of a generic class. However, it is possible, and it will solve your problem in a typesafe way.
1st. declare your map like this
private Map<Integer,Set<String>>[] myMaps = null;
2nd. use a utility function to allocate
#SuppressWarnings("unchecked")
public static <T> T[] newMapArray( int size )
{
return (T[])java.lang.reflect.Array.newInstance(Map.class, size);
}
3rd. allocate myMaps like this
myMaps = newMapArray(numRepeats);