Odd behavior with Maps - java

I am getting a syntax error which I am not able to resolve. I am using Java 1.8.
import java.util.*;
public class datatypetest
{
public static void main(String args[])
{
Map map1 = new HashMap();
map1.put("1", "Deepak");
map1.put("2", "Ajay");
System.out.println(map1);
System.out.println(map1.keySet());
for (Map.Entry<String, String> entry : map1.entrySet())
{
System.out.println(entry.getKey() + "/" + entry.getValue());
}
}
}
But I am getting this error:
incompatible types: Object can not be converted to Entry<String,String>

You created a raw map :
Map map1 = new HashMap();
Change it to:
Map<String,String> map1 = new HashMap<String,String>();
If you instantiate the map as a raw Map, you can't use Map.Entry<String, String> in the loop (you can only use the raw Map.Entry).

You need to use Generics to avoid such Type of Conflicts i.e
Map<String, String> map1 = new HashMap<String, String>();
Generics provides Type Safety.
And in addition I've found in your code that your Class name didn't follow best practices. It indeed must start with Capital letter since it's a best practice entire JAVA world follows
Try This
import java.util.*;
public class DataTypeTest {
public static void main(String args[]){
Map<String, String> map1 = new HashMap<String, String>();
map1.put("1", "Deepak");
map1.put("2", "Ajay");
System.out.println(map1);
System.out.println(map1.keySet());
for (Map.Entry<String, String> entry : map1.entrySet())
{
System.out.println(entry.getKey() + "/" + entry.getValue());
}
}
}
Happy Programming :)

because you have created
Map map1 = new HashMap();
can be of any type(not just string) so java is not allowing you to downcast it.

Related

Java 8 : how to extract a HashMap from a ArrayList of HashMap in Java 8 using streams?

I have the following sample result when I query a database :
dataList = [{ name : name1, rollno: rollno1 }, { name : name2, rollno: rollno2 } ]
I want to convert this list of hashmaps into a single hashmap using Java 8 streams.
I tried using Collectors.toMap() but i am not sure how to refer to rollNo as key and the hashmap as the value inside the toMap method.
Exected output :
{ rollno1 : { name : name1, rollno: rollno1 } , rollno2 : { name : name2, rollno: rollno2 } }
I tried doing it using a for each loop on the list and then adding the rollno as key to a hashmap and the hashmap as value itself of that rollno.
HashMap<String,HashMap<String,String>> newMap = new HashMap();
for(HashMap<String,String> record : dataList){
String key = record.get("rollno").toString();
newMap.put(key,record);
}
Is there a way to refactor this code using functional streams in Java 8?
Will using streams collect method give any performance advantage over the foreach for doing this?
Will appreciate any leads. Thanks
Here's complete example how to do it
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<HashMap<String, String>> input = new ArrayList<>();
HashMap<String, String> subinput1 = new HashMap<>();
subinput1.put("name", "name1");
subinput1.put("rollno", "rollno1");
input.add(subinput1);
HashMap<String, String> subinput2 = new HashMap<>();
subinput2.put("name", "name2");
subinput2.put("rollno", "rollno2");
input.add(subinput2);
HashMap<String, HashMap<String, String>> result = (HashMap<String, HashMap<String, String>>) input.stream()
.collect(Collectors.toMap(v -> (String) v.get("rollno"), e -> e));
System.out.println(result);
}
}
It iterates over a collection of HashMaps, takes the key in which it should be stored in the result HashMap, then it creates a Map of Maps where the key is the "rollno" from the input map, and value is the input map itself.
As I don't know the type of Object you are using, so I am performing this on String. But it is valid for any type of object.
HashMap result = (HashMap<String, HashMap<String, String>>) listOfHashMaps.stream()
.collect(Collectors.toMap(e-> e.get("roll"),e->e));
As type casting will help you to achieve this.
You can use Collectors.toMap with Function.identity() as below,
list.stream()
.collect(toMap(e->e.get("rollno"), Function.identity()));
public static void main(String[] args) {
List<HashMap<String, String>> input = new ArrayList<>();
HashMap<String, String> subinput1 = new HashMap<>();
subinput1.put("name", "name1");
subinput1.put("rollno", "rollno1");
input.add(subinput1);
HashMap<String, String> subinput2 = new HashMap<>();
subinput2.put("name", "name2");
subinput2.put("rollno", "rollno2");
input.add(subinput2);
//Test key conflict
HashMap<String, String> subinput3 = new HashMap<>();
subinput2.put("name", "name3");
subinput2.put("rollno", "rollno2");
input.add(subinput2);
System.out.println("input:"+ JSONObject.toJSONString(input));
HashMap<String, HashMap<String, String>> result = (HashMap<String, HashMap<String, String>>)
input.stream()
.collect(Collectors.toMap(
v -> (String) v.get("rollno"),
Function.identity(),(oldValue, newValue) -> newValue
));
//fastjson hashmap-toString use =
System.out.println(JSONObject.toJSONString(result));
}
Probably something like this:
Map<RollNo, List<Roll>> rollsPerType = rolls.stream()
.collect(groupingBy(Roll::getRollNo));
where Roll is the main object and RollNo is the property inside (since you didn't provide the actual definitions).

Get value of HashMap within TreeMap

I've got a TreeMap that stores a HashMap inside of it. I feel like I should be able to find this, but I just can't seem to find it on Google.
I've got a TreeMap with a HashMap stored inside of it, I iterate over it like so:
while (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
System.out.print(me.getKey() + ": ");
System.out.println(me.getValue());
}
That will print out an output (example line):
I/System.outīš• 32: {walks=32, pic=http://****/images/walkers/chase.png, name=Chase, dist=6096.8589024135445}
I'm wondering how to now grab pic, name, dist from this HashMap.
Edit: I'm not understanding where people missed the point. I put a HashMap into the TreeMap. Inside of the TreeMap is a HashMap. I guess I can show you what a HashMap is, but you guys know that already!
TreeMap dist_mp=new TreeMap();
Map<String, String> mp1 = new HashMap<String,String>();
mp1.put("dist", distanceInMiles + "");
mp1.put("name", obj.getString("first_name"));
mp1.put("pic", obj.getString("pic"));
mp1.put("walks", obj.getString("walks"));
dist_mp.put(distanceInMiles, mp1);
All you need is a cast to the TreeMap values to a Map again:
while (i.hasNext()) {
Map.Entry me = (Map.Entry) i.next();
System.out.print(me.getKey() + ": ");
// Cast to a Map again
Map<String, String> mp = (Map<String, String>) me.getValue();
// get() works now
System.out.print("name = " + mp.get("name"));
System.out.print("pic = " + mp.get("pic"));
System.out.println("dist = " + mp.get("dist"));
}
Need to iterate twice, one for TreeMap and then for HashMap
public static void main(String[] args) {
TreeMap<String, Map<String, String>> dist_mp = new TreeMap<String, Map<String, String>>();
Map<String, String> mp1 = new HashMap<String, String>();
mp1.put("dist", "6096.8589024135445");
mp1.put("name", "Chase");
mp1.put("pic", "http://****/images/walkers/chase.png");
mp1.put("walks", "32");
dist_mp.put("32", mp1);
for (Map.Entry<String, Map<String, String>> entry : dist_mp.entrySet()) {
String key = entry.getKey();
System.out.println(key);
Map<String, String> myMap = entry.getValue();
for (Map.Entry<String, String> entry1 : myMap.entrySet()) {
System.out.println(entry1.getKey() + " => " + entry1.getValue());
}
}
}
output
32
walks => 32
name => Chase
pic => http://****/images/walkers/chase.png
dist => 6096.8589024135445
Your HashMap seems to be holding an object of some class, which is depicted here:
{walks=32, pic=http://****/images/walkers/chase.png, name=Chase, dist=6096.8589024135445}
Identify the class, and if getter methods are available for pic, name, dist, then use them.
I think you are just asking how to get the value associated with a key:
map.get("pic");
You want me.getValue().get("pic"), me.getValue().get("name") and me.getValue().get("dist").
This assumes that you're using generics, that your TreeMap is declared as a Map<Integer, HashMap<String, String>> and that your Map.Entry that you iterate with is declared as a Map.Entry<Integer, HashMap<String, String>>.
Also, you could iterate more easily with a for-each loop.
Map<Integer, HashMap<String, String>> theTreeMap = new TreeMap<>();
// Populate the map here.
for (Map.Entry<Integer, HashMap<String, String>> me : theTreeMap.entrySet()) {
System.out.println(me.getValue().get("pic"));
System.out.println(me.getValue().get("name"));
System.out.println(me.getValue().get("dist"));
}

Easily convert Map<String, Object> to Map<String, String>

An API I am using has a method that returns a Map<String, Object>, but I know the Object's are String's in this case, so I want it as a Map<String, String>.
But for some reason I can't just cast it, Java says Map<String, Object> cannot be casted to Map<String, String>, for some reason.
I used:
Map<String, Object> tempMap = someApiMethodReturningAMap();
Map<String, String> map = new HashMap<String, String>();
for (String i : tempMap.keySet()) {
map.put(i, String.valueOf(tempMap.get(i)));
}
as a workaround, but is there an easier way?
Well you can't safely cast it to a Map<String, String> because even though you know you've only got strings as the values, the compiler doesn't. That's like expecting:
Object x = "foo";
String y = x;
to work - it doesn't; you need to explicitly cast.
Likewise you can explicitly cast here, too, if you go via Object:
Map<String, Object> x = ...;
Map<String, String> y = (Map<String, String>) (Object) x;
Now you'll get a warning saying that it's an unchecked cast, because unlike the earlier "object to string" cast, there's no execution-time check that it's really valid. Type erasure means that a map doesn't really know its key/value types. So you end up with checking only being done when elements are fetched:
import java.util.*;
class Test {
public static void main(String[] args) {
Map<String, Object> x = new HashMap<>();
x.put("foo", "bar");
x.put("number", 0);
Map<String, String> y = (Map<String, String>) (Object) x;
// This is fine
System.out.println(y.get("foo"));
// This goes bang! It's trying to cast an Integer to a String
System.out.println(y.get("number"));
}
}
So if you really want to avoid creating a new map, this "cast via Object" will work - but it's far from ideal.
Your approach is safer, although you can make it slightly more efficient by avoiding the lookup:
public static Map<String, String> copyToStringValueMap(
Map<String, Object> input) {
Map<String, String> ret = new HashMap<>();
for (Map.Entry<String, Object> entry : input.entrySet()) {
ret.put(entry.getKey(), (String) entry.getValue());
}
return ret;
}
A Java 8 solution:
private Map<String, String> stringifyValues(Map<String, Object> variables) {
return variables.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, e -> (String) e.getValue()));
}
Good solutions here, but I want to add another one that taking into consideration handling null values:
Map<String,Object> map = new HashMap<>();
Map<String,String> stringifiedMap = map.entrySet().stream()
.filter(m -> m.getKey() != null && m.getValue() !=null)
.collect(Collectors.toMap(Map.Entry::getKey, e -> (String)e.getValue()));

"Incompatible types" when accessing Map#entrySet()

I am working on a simple config file reader for fun, but I am getting an odd error while writing the test method. In it is a for loop, and I have made sure that it causes the problem. It gives me this compilation error:
Incompatible types:
Required: java.util.Map.Entry
Found: java.lang.Object
The Map declaration is this:
Map<String, String> props = new HashMap<String, String>();
The for loop is written as below:
for (Map.Entry<String, String> entry : props.entrySet()) {
//Body
}
An SSCCE without imports which demonstrates the problem (At least in IntelliJ):
public class A {
public static void main(String[] args) {
Map<String, String> props = new HashMap<String, String>();
for (int i = 0; i < 100; i++) {
props.put(new BigInteger(130, random).toString(32), new BigInteger(130, random).toString(32));
}
for (Map.Entry<String, String> entry : props.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
}
map is a Map<String, String>, so that can't be the problem. I have googled alternative methods of doing this, but the main one people use seems to be this one! Yet for some reason it still fails. Any help would be appreciated. If you offer an alternative solution, please make sure it is fast - these config files could potentially be huge.
Here's a demonstration of what you may be doing - it is difficult to be sure without more code.
class ATest<T> {
Map<String, String> props = new HashMap<String, String>();
void aTest() {
// Works fine.
for (Map.Entry<String, String> entry : props.entrySet()) {
}
}
void bTest() {
ATest aTest = new ATest();
// ERROR! incompatible types: Object cannot be converted to Entry<String,String>
for (Map.Entry<String, String> entry : aTest.props.entrySet()) {
}
}
void cTest(Map props) {
// ERROR! incompatible types: Object cannot be converted to Entry<String,String>
for (Map.Entry<String, String> entry : props.entrySet()) {
}
}
}
Notice that in bTest I create an ATest without its generic type parameter. In that situation Java removes all generic information from the class, including, as you will see, the <String,String> from the props variable inside it.
Alternatively - you may be accidentally removing the generic nature of the properties map - like I demonstrate in cTest.
Try to declare your map as a HashMap.
HashMap<String, String> props = new HashMap<String, String>();
This is what solved my problem.

Get values of Map from a Map

In my code i have a
Map<String,Map<String,customObject>>
I am not sure how to iterate over this map and get the values from it.
What i am trying to do here is get the enclosing Map by passing in the key to the external Map.
When i get the enclosing map i need to iterate over it and get key and value from it.
Can you please let me know how i can do this as i am kind of stuck here.
Any example or code of a similar type can be of a great help to understand it better.
Thanks
Vikeng21
You can use the entry set of both Maps. something like this:
Map<String,Map<String,String>> map1 = ...
Set<Entry<String,Map<String,customObject>>> entrySet1 = map1.entrySet();
for (Entry<String, Map<String, customObject>> entry1 : entrySet1) {
Map<String,String> map2 = entry1.getValue();
Set<Entry<String, customObject>> entrySet2 = map2.entrySet();
for (Entry<String, customObject> entry2 : entrySet2) {
System.out.println(entry1.getKey() +" -> "+entry2.getKey()+" -> "+entry2.getValue());
}
}
To iterate over hashmap entries...
for (Map.Entry<String, Map<String, Object>> ent : hashmap.entrySet())
{
//ent.getKey(); is the key [String]
//ent.getValue(); is the value [Map<String, Object>]
}
Now work out from there, it's basically the same.
I am not sure how to iterate over this map and get the values from it
You would iterate over the map's values like with any maps - see below an example that uses such a structure.
Map<String, CustomObject> innerMap = new HashMap<String, CustomObject> ();
innerMap.put("abc", new CustomObject());
Map<String, Map<String, CustomObject>> externalMap = new HashMap<String, Map<String, CustomObject>> ();
externalMap.put("map1", innerMap);
//iterate over all the maps contained in externalMap
for (Map<String, CustomObject> inner : externalMap.values()) {
System.out.println(inner);
}
If you also need to access the keys, you can iterate over the entry set:
for (Entry<String, Map<String, CustomObject>> e : externalMap.entrySet()) {
System.out.println(e.getKey()); //map1
System.out.println(e.getValue()); //innerMap
}
I think this example will give your answer....
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class MapInMap {
public static void main(String[] args) {
Map<String, MyObj> innerMap01 = new HashMap<String, MyObj>();
Map<String, MyObj> innerMap02 = new HashMap<String, MyObj>();
innerMap01.put("OneOne", new MyObj());
innerMap02.put("TwoOne", new MyObj());
Map<String, Map<String, MyObj>> maps = new HashMap<String, Map<String, MyObj>>();
maps.put("One", innerMap01);
maps.put("Two", innerMap02);
for (Entry<String, Map<String, MyObj>> map : maps.entrySet()) {
for (Entry<String, MyObj> innerObject : map.getValue().entrySet()) {
// your logic
}
}
}
}
class MyObj {
int i;
}

Categories

Resources