Sorry, new to java, actally coding in jython but I would think java syntax should work.
I have a hashmap that looks like this:
Hashmap = {21035179={WEIGHT=1}, 2300={WEIGHT=0}, 21035180={EMA_FIRST=1000.11615393169158, EMA_SECOND=966.8684105279658}}
The values are of an enum type, not sure how that changes things cause I'm not that familiar with that type.
I want to get the weight of 2300, I would think the syntax for this is:
Count = 2300
Hashmap.get(Count).get(enum.WEIGHT)
but this doesn't work, I get a None type back.
What am I doing wrong here?
Answering for java, your structure seems to be Integer -> enum -> double. This would be represented in Java as:
public enum Field {
WEIGHT, EMA_FIRST, EMA_SECOND;
}
Map<Integer, Map<Field, Double>> myMap
Because you are using an enum as the key, you should create the values as EnumMap:
myMap.put(2300, new EnumMap(Field.class));
myMap.get(2300).put(Field.WEIGHT, 34.7);
Getting the weight for 2300 would then be myMap.get(2300).get(Field.WEIGHT).
Related
There's a way to handle this validation ?
class java.lang.Integer cannot be cast to class java.lang.String
Code:
private List<Map<String,String>> getEmpRegistry(
List<Map<String,String>> tblObjRowsList,
Integer rowNumber
){
List<Map<String,String>> empRegistry = new ArrayList<>();
for (Map<String,String> empR : tblObjRowsList){
if (empR.get("id").equals(rowNumber)){
empRegistry.add(empR);
}
}
return empRegistry;
}
Looks wrong, because I can't compare String and Integer.
But for some reason tblObjRowsList is extracted from stored procedure in MySQL via Spring Data:
#Query(value="CALL SP_ObjsRowDetails2(:Id,:templateId,:strMode)",nativeQuery = true)
List<Map<String,String>> getRowDetail (#PathParam("Id") Integer id,
#PathParam("templateId") Integer templateId,
#PathParam("strMode") Integer strMode);
Extract the data like this:
I tried:
Integer.parseInt(empR.get("id")).equals(rowNumber)
Integer.parseInt(empR.get("id").toString()).equals(rowNumber)
empR.get("id").toString().equals(String.valueOf(rowNumber))
And the most interesting thing is:
Doesn't make sense, if the source variable is Map<String,String>
That declaration of List<Map<String,String>> getRowDetail(...) is probably a "lie". That's the problem with runtime, dynamic code generation...
Spring data generates the implementation for you, and there is no proof that it will generate a Map<String, String> in reality, it all depends on what the SQL type will actually be in your procedure
Spring can and will produce a Map but you can not know what types lie therein, the actual types will be chosen once the metadata for the SQL result set comes back.
The compiler is happy, because generics are erased after compilation anyway, so as long as it's a Map, it's fine.
In the end you only realise Spring did not do "the right thing" (or actually, what you expected, because in its view it did the right thing) until runtime.
There is no easy way out. Either you fully acknowledge the unknowable nature of the contents of the map, and declare a Map<Object, Object> as the return type. And your code will have to cast to operate on the data.
Or you make sure you adapt the Java to the SQL or vice-versa with less generic types (eg <String, Integer>) - and find a way to make sure nobody changes the SQL without applying the change to the Java side, or vice-versa.
I believe that instead of Map<String, String> use Map<String, Object> and then according to the type inside of the value just cast it to to integer, string, or whatever.
I am currently reading "Core Java for the Impatient" by Horstmann (I recommend it, love the concise style) and I have a trouble understanding one of the exercises pertaining to the collection API. The exercise is as follows:
I encouraged you to use interfaces instead of concrete data structures, for example, a
Map instead of a TreeMap. Unfortunately, that advice goes only so far. Why can’t
you use a Map<String, Set<Integer>> to represent a table of contents?
(Hint: How would you initialize it?) What type can you use instead?
The following code compiles and works without a problem though, even though the interfaces were used for variable declarations. What am I missing?
Map<String, Set<Integer>> toc = new HashMap<>();
toc.put("element1", IntStream.of(1, 2, 3).boxed().collect(Collectors.toSet()));
toc.put("element2", IntStream.of (3, 4, 7).boxed().collect(Collectors.toSet()));
toc.forEach( (k, v) -> {
System.out.print(k + " ");
v.forEach(val -> System.out.print(val + " "));
System.out.println();
} );
}
An interface like Map is a supertype for all interfaces that inherit it and all classes that implement it. So TreeMap inherits from Map, and because you can always assign to a variable any reference that is of a subtype, it's perfectly acceptable to assign a TreeMap reference to a Map variable. This is called a widening reference conversion
https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.5
"Widening reference conversions never require a special action at run time and therefore never throw an exception at run time. They consist simply in regarding a reference as having some other type in a manner that can be proved correct at compile time."
So, yes, you certainly can use a Map<String, Set<Integer>> to represent something in your domain model, but you can't instantiate an interface directly; you must instantiate a concrete type (class) that implements it. This is exactly what you did when you declared
Map<String, Set<Integer>> toc = new HashMap<>();
As an extension of this principle, you could just as easily write
AbstractMap<String, Set<Integer>> toc = new HashMap<>();
since AbstractMap is also a supertype of HashMap.
In general you want to declare the widest type for the variable that can hold the largest possible set of subtype references that work in your logic. If you need a sorted map, then 'Map' is too wide; it doesn't enforce sortedness. You'd have to declare the variable as TreeMap , or better, SortedMap for that.
Usually the interface is the widest applicable type, but you have to think about it in case it's not.
EDIT: Mentioned SortedMap in light of comment.
I have got in touch with book's author and he agreed that question was unclear and it was to lead the reader to use wildcard types. The exercise in question was changed to:
Suppose you have a method parameter of type Map<String, Set<Integer>>, and someone calls your method with a HashMap<String, HashSet<Integer>>. What happens? What parameter type can you use instead?
The answer is that in this case one should use the wildcard type: Map<String, ? extends Set<Integer>>.
Is there a data structure in Java which can hold more than 4 values?
So something along the lines of
Map<String, String, String, String>;
This is needed to be able to reduce the number of if else statements I have. I would like to be able to do the following.
check if the data structure contains an element which matches a certain value, if it does then it assigns a link(which is string) to a variable and then adds a code and message to another variable which is related to that link.
if not is there a good workout around to achieve this?
Is there a data structure in Java which can hold more than 4 values?
There are lots of them.
The simplest is probably String[] which can hold 4 strings if you instantiate it like this:
new String[4]
And other Answers give other data structures that might meet your actual (i.e. unstated) requirements.
However, it is probably possible ... let alone sensible ... for us to enumerate all of the possible data structures that can meet your stated requirement.
Hint: you should try to explain how this data structure needs to work.
Hint 2: "the lines of Map<String, String, String, String>" does not help us understand your real requirement because we don't know what you mean by that.
UPDATE - Your explanation is still extremely vague, but I think you need something like this:
Map<String, MyRecord>;
public class MyRecord {
private String link;
private String code;
private String message;
// add constructor, getters, setters as required
}
There is nothing in the standard libraries, but Guava has a nice implementation; called
Multimap
If Guava is not an option in your environment, you will have to re-invent the wheel though.
Use can use MultiMap on Apache,
A MultiMap is a Map with slightly different semantics. Putting a value into the map will add the value to a Collection at that key. Getting a value will return a Collection, holding all the values put to that key
MultiMap mhm = new MultiValueMap();
mhm.put(key, "A");
mhm.put(key, "B");
mhm.put(key, "C");
Collection coll = (Collection) mhm.get(key);
Use Map of map:
Map<String, Map<String, Map<String, String>>>
Reading your question, It seams like you simply need a 'key-value' pair. Key being a 'String', which you have referred as 'a certain value' in your question. Value is a kind of wrapper object wrapping three Strings which you have referred as 'link, code and message'.
I suggest you can simply use
HashMap < String, Wrapper > map;
You can create a class ' Wrapper.java' which can contain three Strings, as instance fields
String link,code,message;
You can instantiate these fields in constructor and later can retrieve them using getter methods or also can have setters to set the values you need. You can provide a better contextual name to the class 'Wrapper.java'.
I have studied question 15588452 to know how to build a symbol table.
My question is the implementation details how to make a symbol table support more data types,
I don't want to just support integers like:
memory = new HashMap<String, Integer>();
As far as I can think out(pardon me, I haven't finished the whole dragon book about compilers), are the following 2 way.
First way : build a map contains a Symbol object:
Map<String, Symbol> symbolMap = new LinkedHashMap<String, Symbol>();
And Symbol object have name, type, data block info like below :
public class Symbol {
protected Scope scope; // scope info
protected String name;
protected ValueType type;//contains type info ,like int float
protected Object value;//contains the real value
}
when resolve its value, we can make type cast, cast to the type it need like:
float a = (float)symbol.value;//convert object field to float
this will cause lots of if..else type check.
Or we calculate the memory size and resolve the memory block.
Second way : use more map that contains different type data,when make assignment like :
Map<String, Integer> intMap = new LinkedHashMap<String, Integer>();
Map<String, Double> doubleMap = new LinkedHashMap<String, Double>();
int a = 5;//put in intMap
double b = 1.34;//put in doubleMap
we put it in different map as well as we resolve it, this look a little stupid.
How to support more types in a gentle way ?
Anyone who has experienced, please give some insights, thank you .
To be more specific, you want more than just a symbol table. You want to be able to store values associated with those symbols at runtime. For such an interpreter, people tend to make typed memory cells kind of like your first way. Typically symbols have a data type pointer and then, if in an interpreter, a reference to the data. You look things up in the current scope and it walks up the scope tree until it finds the first symbol and then simply gets its value out.
So I have two questions about HashMaps in Java:
What is the correct way to initialize a HashMap? I think it might be best in my situation to use:
HashMap x = new HashMap();
But Eclipse keeps suggesting that I use:
HashMap<something, something> map = new HashMap();
Which is better?
Can a HashMap hold different types of objects/data types as values? For example, would this work and be OK:
map.put("one", 1);
map.put("two", {1, 2});
map.put("three", "hello");
In the first put(), I want an int as a value, in the second an int[], and third a string. Is this okay to do in Java with HashMaps? Also, is it okay to store a HashMap as a value within a HashMap?
It really depends on what kind of type safety you need. The non-generic way of doing it is best done as:
Map x = new HashMap();
Note that x is typed as a Map. this makes it much easier to change implementations (to a TreeMap or a LinkedHashMap) in the future.
You can use generics to ensure a certain level of type safety:
Map<String, Object> x = new HashMap<String, Object>();
In Java 7 and later you can do
Map<String, Object> x = new HashMap<>();
The above, while more verbose, avoids compiler warnings. In this case the content of the HashMap can be any Object, so that can be Integer, int[], etc. which is what you are doing.
If you are still using Java 6, Guava Libraries (although it is easy enough to do yourself) has a method called newHashMap() which avoids the need to duplicate the generic typing information when you do a new. It infers the type from the variable declaration (this is a Java feature not available on constructors prior to Java 7).
By the way, when you add an int or other primitive, Java is autoboxing it. That means that the code is equivalent to:
x.put("one", Integer.valueOf(1));
You can certainly put a HashMap as a value in another HashMap, but I think there are issues if you do it recursively (that is put the HashMap as a value in itself).
This is a change made with Java 1.5. What you list first is the old way, the second is the new way.
By using HashMap you can do things like:
HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();
....
Doohickey result = ourMap.get("bob");
If you didn't have the types on the map, you'd have to do this:
Doohickey result = (Doohickey) ourMap.get("bob");
It's really very useful. It helps you catch bugs and avoid writing all sorts of extra casts. It was one of my favorite features of 1.5 (and newer).
You can still put multiple things in the map, just specify it as Map, then you can put any object in (a String, another Map, and Integer, and three MyObjects if you are so inclined).
Eclipse is recommending that you declare the type of the HashMap because that enforces some type safety. Of course, it sounds like you're trying to avoid type safety from your second part.
If you want to do the latter, try declaring map as HashMap<String,Object>.
The way you're writing it is equivalent to
HashMap<Object, Object> map = new HashMap<Object, Object>();
What goes inside the brackets is you communicating to the compiler what you're going to put in the HashMap so that it can do error checking for you. If Object, Object is what you actually want (probably not) you should explicitly declare it. In general you should be as explicit as you can with the declaration to facilitate error checking by the compiler. What you've described should probably be declared like this:
HashMap<String, Object> map = new HashMap<String, Object>();
That way you at least declare that your keys are going to be strings, but your values can be anything. Just remember to use a cast when you get a value back out.
The 2nd one is using generics which came in with Java 1.5. It will reduce the number of casts in your code & can help you catch errors at compiletime instead of runtime. That said, it depends on what you are coding. A quick & dirty map to hold a few objects of various types doesn't need generics. But if the map is holding objects all descending from a type other than Object, it can be worth it.
The prior poster is incorrect about the array in a map. An array is actually an object, so it is a valid value.
Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object
Also, since HashMap is an object, it can also be a value in a HashMap.
A HashMap can hold any object as a value, even if it is another HashMap. Eclipse is suggesting that you declare the types because that is the recommended practice for Collections. under Java 5. You are free to ignore Eclipse's suggestions.
Under Java 5, an int (or any primitive type) will be autoboxed into an Integer (or other corresponding type) when you add it to a collection. Be careful with this though, as there are some catches to using autoboxing.
Eclipse is suggesting you to define generic type so that you can have type safety. You can write
Map m = new HashMap();
which does not ensure type safety but following will ensure type safety
Map<Object,Object> = new HashMap<Object,Object>();
The Object can be any type such as String, Integer etc.
Map.of literals
As of Java 9, there is yet another way to instantiate a Map. You can create an unmodifiable map from zero, one, or several pairs of objects in a single-line of code. This is quite convenient in many situations.
For an empty Map that cannot be modified, call Map.of(). Why would you want an empty set that cannot be changed? One common case is to avoid returning a NULL where you have no valid content.
For a single key-value pair, call Map.of( myKey , myValue ). For example, Map.of( "favorite_color" , "purple" ).
For multiple key-value pairs, use a series of key-value pairs. ``Map.of( "favorite_foreground_color" , "purple" , "favorite_background_color" , "cream" )`.
If those pairs are difficult to read, you may want to use Map.of and pass Map.Entry objects.
Note that we get back an object of the Map interface. We do not know the underlying concrete class used to make our object. Indeed, the Java team is free to used different concrete classes for different data, or to vary the class in future releases of Java.
The rules discussed in other Answers still apply here, with regard to type-safety. You declare your intended types, and your passed objects must comply. If you want values of various types, use Object.
Map< String , Color > preferences = Map.of( "favorite_color" , Color.BLUE ) ;
In answer to your second question: Yes a HashMap can hold different types of objects. Whether that's a good idea or not depends on the problem you're trying to solve.
That said, your example won't work. The int value is not an Object. You have to use the Integer wrapper class to store an int value in a HashMap