I want to order information about events I got as HTML from a website (Category, multiple events in that category, information about one specific event) in a big HashMap and what I tried looks like this:
HashMap categoryMap = new HashMap();
HashMap eventMap = new HashMap();
HashMap singleEventMap = new HashMap();
categoryMap.put(eventCategory, eventMap);
eventMap.put(eventTitle, singleEventMap);
singleEventMap.put("starttime", eventTime);
singleEventMap.put("location", eventLocation);
singleEventMap.put("description", eventDescription);
I`m used to python dictonaries and can't find, how I can add another event to the category or how I can access the stored information in Java.
I would be glad if anyone could give me a code example or a link with a similar problem or a good explanation.
1) Do not use raw generic types.
Always specify the type arguments. You should also program to the interface. E.g.
Map<String, Map<String, Map<String, Object>>> categoryMap = new HashMap<>();
Map<String, Map<String, Object>> eventMap = new HashMap<>();
Map<String, Object> singleEventMap = new HashMap<>();
2) Java is an Object-Oriented language, use it.
E.g. create an Event class with fields starttime, location, and description.
public class Event {
private final LocalDateTime starttime;
private final String location;
private final String description;
public Event(LocalDateTime starttime, String location, String description) {
this.starttime = starttime;
this.location = location;
this.description = description;
}
public LocalDateTime getStarttime() {
return this.starttime;
}
public String getLocation() {
return this.location;
}
public String getDescription() {
return this.description;
}
}
Then use:
Map<String, Map<String, Event>> categoryMap = new HashMap<>();
Map<String, Event> eventMap = new HashMap<>();
3) To add another event:
Create another instance of singleEventMap, add the properties and add it to the eventMap.
Your way:
HashMap categoryMap = new HashMap();
HashMap eventMap = new HashMap();
categoryMap.put(eventCategory, eventMap);
Map singleEventMap = new HashMap();
eventMap.put(eventTitle1, singleEventMap);
singleEventMap.put("starttime", starttime1);
singleEventMap.put("location", location1);
singleEventMap.put("description", description1);
singleEventMap = new HashMap();
eventMap.put(eventTitle2, singleEventMap);
singleEventMap.put("starttime", starttime2);
singleEventMap.put("location", location2);
singleEventMap.put("description", description2);
The Java way:
Map<String, Map<String, Event>> categoryMap = new HashMap<>();
Map<String, Event> eventMap = new HashMap<>();
categoryMap.put(eventCategory, eventMap);
eventMap.put(eventTitle1, new Event(starttime1, location1, description1));
eventMap.put(eventTitle2, new Event(starttime2, location2, description2));
Or if they have different categories:
Map<String, Map<String, Event>> categoryMap = new HashMap<>();
Map<String, Event> eventMap1 = new HashMap<>();
categoryMap.put(eventCategory1, eventMap1);
eventMap1.put(eventTitle1, new Event(starttime1, location1, description1));
Map<String, Event> eventMap2 = new HashMap<>();
categoryMap.put(eventCategory2, eventMap2);
eventMap2.put(eventTitle2, new Event(starttime2, location2, description2));
Related
My problem is as follows:
My service loops over items that are passed as args. For each item, i make two calls. My first price call gives me 9999 which means nothing was returned. That's fine - that's possible. My stock call works perfectly and i get the correct stock value returned. On the second iteration, my price call returns the same value as the previous stock call.
So, i get 9999 for price, then 150 for stock, then 150 for price. What's throwing me is that the price out parm is 6th, whereas the stock out parm is 8th. No idea how it would retain that value in a different position.
It seems that my jdbctemplate isn't being cleared or it's storing previous out params. Here's the code involved:
MyService.java
#Service
public class MyService extends BaseService implements MyInterface{
protected static final Logger logger = LoggerFactory.getLogger(MyService.class);
#Autowired
private MyDAO myDAO;
public myResponse checkOrder(args...)
{
for(something in args){
// PRICE
// Grab price data
LinkedHashMap<String, Object> priceCallInParams = new LinkedHashMap<String, Object>();
priceCallInParams .put("param1", "param1val");
priceCallInParams .put("param2", "param2val");
priceCallInParams .put("param3", "param3val");
priceCallInParams .put("param4", "param4val");
priceCallInParams .put("param5", "param5val");
LinkedHashMap<String, Object> priceCallOutParams = new LinkedHashMap<String, Object>();
priceCallOutParams .put("price", "0");
logger.debug("Getting data...");
Map<String, Object> priceData = new HashMap<String, Object>();
priceData = myDAO.checkPrice(priceCallInParams , priceCallOutParams );
BigDecimal unitPrice = new BigDecimal(9999);
if (!priceData .get("PRCE").toString().trim().equals("")){
unitPrice = new BigDecimal(priceData.get("PRCE").toString().trim());
}
System.out.println("PRC - "+unitPrice);
// AVAILABLE STOCK
// Grab check stock data
LinkedHashMap<String, Object> checkStockInParms = new LinkedHashMap<String, Object>();
checkStockInParms.put("param1", "param1val");
checkStockInParms.put("param2", "param2val");
checkStockInParms.put("param3", "param3val");
checkStockInParms.put("param4", "param4val");
checkStockInParms.put("param5", "param5val");
checkStockInParms.put("param6", "param6val");
checkStockInParms.put("REQQTY", "123");
LinkedHashMap<String, Object> checkStockOutParms = new LinkedHashMap<String, Object>();
checkStockOutParms .put("AVAILQTY", "0");
checkStockOutParms .put("NEXTDUE"," ");
checkStockOutParms .put("NEXTQTY","0");
logger.debug("Getting data...");
Map<String, Object> checkStockDat = new HashMap<String, Object>();
checkStockDat = myDAO.checkStock(checkStockInParms , checkStockOutParms );
// Output quantity
int AvailQTY = Integer.valueOf(checkStockDat.get("AVAILQTY").toString().trim());
if (reqBIT.getRequestedQuantity()>AvailQTY) {
resBIT.setConfirmedQuantity(AvailQTY);
}
else {
resBIT.setConfirmedQuantity(reqBIT.getRequestedQuantity());
}
}
}
}
MyDAO.java
#Component
public class MyDAO extends BaseDAO{
protected static final Logger logger = LoggerFactory.getLogger(OrderDAO.class);
public Map<String, Object> checkStock(LinkedHashMap<String, Object> inparms, LinkedHashMap<String, Object> outparms){
StringBuilder builtSQL = new StringBuilder();
builtSQL.append("CALL ");
builtSQL.append("checkstock ");
// just generates our param string (?,?,?...)
builtSQL.append(DataUtilities.genParmPlaceholderStringFromTotal(inparms.size()+outparms.size()));
return executeStoredProcedure(builtSQL.toString(), inparms, outparms);
}
public Map<String, Object> checkPrice(LinkedHashMap<String, Object> inparms, LinkedHashMap<String, Object> outparms){
logger.debug("CheckPrcc Initiated");
StringBuilder builtSQL = new StringBuilder();
builtSQL.append("CALL ");
builtSQL.append("checkprice ");
// just generates our param string (?,?,?...)
builtSQL.append(DataUtilities.genParmPlaceholderStringFromTotal(inparms.size()+outparms.size()));
return executeStoredProcedure(builtSQL.toString(), inparms, outparms);
}
}
BaseDAO.java
public class BaseDAO{
#Autowired
protected JdbcTemplate jdbcTemplate;
protected static final Logger logger = LoggerFactory.getLogger(BaseDAO.class);
protected Map<String, Object> executeStoredProcedure(String SQL, LinkedHashMap<String, Object> inParams, LinkedHashMap<String, Object> outParams){
Map<String, Object> result = new HashMap<String, Object>();
List<SqlParameter> declaredParameters = new ArrayList<SqlParameter>();
for (Map.Entry<String, Object> entry : inParams.entrySet()) {
declaredParameters.add(new SqlParameter(entry.getKey().toString(), Types.CHAR));
}
for (Map.Entry<String, Object> entry : outParams.entrySet()) {
declaredParameters.add(new SqlOutParameter(entry.getKey().toString(), Types.CHAR));
}
result = jdbcTemplate.call(new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection connection)
throws SQLException {
CallableStatement callableStatement = connection.prepareCall(SQL);
int index = 0;
for (Map.Entry<String, Object> entry : inParams.entrySet()) {
index++;
callableStatement.setString(index, entry.getValue().toString());
}
for (Map.Entry<String, Object> entry : outParams.entrySet()) {
index++;
callableStatement.registerOutParameter(index, Types.CHAR);
}
return callableStatement;
}
}, declaredParameters);
return result;
}
}
My service is invoked from my rest controller, which pass the args (if that matters).
I've been racking my brain and can't find any information regarding this issue. I'm new to spring boot and Java. I don't believe i'm doing something too egregious.
In our situation, this was being caused our i-series. If no data is present to return, the system still returns 10 chars from memory - being the last value it just returned. The solution is to always populate the return value to clear the memory.
Not spring-boot after all!
I am working on REST API service and each time when exception is occured I need to show in logs params , method and class name where this exception happened. So i have singleton class with method
public void log(final String className,String methodName,final Map<String,String> params,final String cause) {
final StringBuilder result=new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
result.append(entry.getKey()+" "+entry.getValue()+" ");
}
log.info("\n\t\t\tClass: "+className+"\n\t\t\t Method: "+methodName+"\n\t\t\t Params: "+result.toString()+" \n\t\t\t "+"Reason: "+cause);
}
Example of use
public String checkSession(String sid) {
final Map<String, String> params = new HashMap<String, String>();
params.put("sid", sid);
if (sid.isEmpty()) {
logger.log(this.getClass().getSimpleName(), "checkSession", params, " not valid session");
return Enums.Error.WRONG_SESSION.toString();
}
}
However in each method I need to initialize this map with all params. How can I write method that will return Map for all methods?
For example I have two methods
public String createPass(String name,String surname) {
final Map<String, String> params = new HashMap<String, String>();
params.put("name", name);
params.put("surname", surname);
}
public String checkSession(String sid) {
final Map<String, String> params = new HashMap<String, String>();
params.put("sid", sid);
}
And method that I need is something like
public HashMap<String,String> method(String args...){
final Map<String, String> params = new HashMap<String, String>
for(...)
map.put("parameter","parameterName");
}
I think the best you can do here is something like this:
public Map<String,String> paramsToMap(String... params){
final Map<String, String> map = new HashMap<>();
for(int i=0; i<params.length-1; i=i+2) {
map.put(params[i], params[i+1]);
}
return map;
}
And you call it this way:
public String createPass(String name, String surname) {
final Map<String, String> params = paramsToMap("name", name, "surname", surname);
}
public String checkSession(String sid) {
final Map<String, String> params = paramsToMap("sid", sid);
}
I wish we could use reflection, however the parameter names are removed at compile time and you are left with arg0, arg1, etc ... So it is not possible to achieve what you want using reflection. You have to input the parameter names yourself.
Also as a side note, I think you would be better off using a Map<String, Object> and let the log method sort out how to print it out to the logs. Probably using String.valueOf()
I have a map defined like this:
Map<Long, Long> foo = new TreeMap<Long, Long>();
For each entry into the map, I also want to map those entries to a Boolean. How can I do this? This is what I tried so far but it doesn't look right. What I want to achieve is that for every entry in mask, there should be a corresponding Boolean value that it is assigned to.
Map<Long, Boolean> mask = new HashMap<Long, Boolean>();
SortedMap<Long, Map<Long, Boolean>> pairs = new TreeMap<Long, Map<Long, Boolean>>();
mask.put(new Long(2), Boolean.FALSE);
mask.put(new Long(3), Boolean.FALSE);
mask.put(new Long(3), Boolean.FALSE);
pairs.put(new Long(1), new Long(2));
pairs.put(new Long(1), new Long(3));
pairs.put(new Long(2), new Long(3));
The constraint is that I can only use the built-in types. I had a solution before which had a custom object which allowed me to easily achieve this but due to the project design, I cannot create new types.
Create a class that encapsulates both values and make a map of that:
class Pair {
public final boolean booleanValue;
public final long longValue;
public Pair(boolean booleanValue, long longValue) {
this.booleanValue = booleanValue;
this.longValue = longValue;
}
}
Map<Long,Pair> map = new HashMap<>();
map.put(1L, new Pair(false, 123));
map.put(2L, new Pair(true, 456));
map.put(3L, new Pair(false, 789));
Or use two maps having the same keys:
Map<Long,Boolean> map1 = new HashMap<>();
Map<Long,Long> map2 = new HashMap<>();
map1.put(1L, false); map2.put(1L, 123L);
map1.put(2L, true); map2.put(2L, 456L);
map1.put(3L, false); map2.put(3L, 789L);
If I understand you, you want to map both a Long and a Boolean to the same key entry?
If that's the case, and you can't create your own custom objects, you just need to have two maps:
Map<Long, Long> pairs = new HashMap<Long, Long>();
Map<Long, Boolean> mask = new HashMap<Long, Boolean>();
Then just use the same key entry for both:
pairs.put(1L, 5L);
mask.put(1L, false);
pairs.put(2L, 20L);
mask.put(2L, true);
and so on.
Create a new object that has a Long and Boolean and that object put into the map.
What about a holder ?
private class MyHolder
{
public Boolean boolValue;
public Long longValue;
}
Map<Long, MyHolder> myMap = new HashMap<Long, MyHolder>();
MyHolder h = new MyHolder();
h.boolValue = true;
h.longValue = 1L;
myMap.put(1L, h);
I am trying to create a TreeMap with a generic type but I am unable to. I am doing this because my map can like these:
Map<String, QueryTerm> terms = new TreeMap<String, QueryTerm>();
Map<String, String> params = new TreeMap<String, String>();
So instead of creating multiple functions to handle the maps with different types I want to create one which both types.
How can I do this and what am I doing wrong?
Function:
private Map<String, ? extends Object> setDatumMap(UserSession session, String parameterName)
{
Map<String, ? extends Object> map = new TreeMap<String, ? extends Object>();
//Get comma delimited list of filter keys. Split them and use them to retrieve associated values.
String sFilters = (String) session.getAttribute(parameterName);
String[] filterList = sFilters.split(",");
for(String filterName : filterList)
{
String filterValue = (String) session.getAttribute(filterName);
if (filterValue != null && !filterValue.isEmpty())
{
filter.put(filterName, setQueryTermList(filterValue, ListType.BOOLEAN_LIST));
}
}
return filter;
}
You should simply instantiate the map like so:
Map<String, Object> map = new TreeMap<String, Object>();
You can't instantiate using a wildcard, and it's not necessary unless you expect that the compiler will cast to the appropriate class by guessing what value you are going to get. We didn't get there yet.
you need to change you this line :
private Map<String, ? extends Object> setDatumMap(UserSession session, String parameterName)
{
Map<String, ? extends Object> map = new TreeMap<String, ? extends Object>();
//rest of your code
To
private Map<String, Object> setDatumMap(UserSession session, String parameterName)
{
Map<String, Object> map = new TreeMap<String, Object>();
//rest of your code.
This will work.
I am doing the following:
IronRunId Id = new IronRunId("RunObject", "Runid1", 4);
ObjectMapper MAPPER = new ObjectMapper();
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("RunId", Id);
String json = MAPPER.writeValueAsString(map);
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map1 = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
IronRunId runId = (IronRunId) (map1.get("RunId"));
But this gives me an error: Cannot cast java.util.LinkedHashMap to IronRunId
Why is the object returned by map.get() of type linkedhashmap?
On the contrary, if I do:
List<Object> myList = new ArrayList<Object>();
myList.add("Jonh");
myList.add("Jack");
map.put("list", myList);
Then the object returned by map.get() after doing mapper.readValue is of type ArrayList.
Why the difference? Inserting default types into the map returns the correct object. But inserting custom made object in the map does not.
Does anyone know how to do this?
Map<String, Object> map1 = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});
basically translated to, return me a Map with keys of type String and values of type Object. So, Jackson gave you keys of type String and values of type Object. Jackson doesn't know about your custom object, thats why it gave you its own native bound for Object which is a Map, specifically, a LinkedHashMap, and thus the reason why your are getting a LinkedHashMap when doing a get to the returned Map
So change it to :
Map<String, IronRunId> map1 = mapper.readValue(json, new TypeReference<Map<String, IronRunId>>() {});
Also, it is a good practice to declare an Object of its interface type than its concrete type. So instead of
HashMap<String, Object> map = new HashMap<String, Object>();
make it
Map<String, Object> map = new HashMap<String, Object>();
Edit
As a response to your added questions, you can create a wrapper object that will handle all your objects. Something like this.
class Wrapper{
private IronRunId ironRunId;
private long time;
private Map<String, String> aspects;
private String anotherString;
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public Map<String, String> getAspects() {
return aspects;
}
public void setAspects(Map<String, String> aspects) {
this.aspects = aspects;
}
public String getAnotherString() {
return anotherString;
}
public void setAnotherString(String anotherString) {
this.anotherString = anotherString;
}
public IronRunId getIronRunId() {
return ironRunId;
}
public void setIronRunId(IronRunId ironRunId) {
this.ironRunId = ironRunId;
}
}
You can then store different objects in this class.
Revised version
public static void main(String[] args) throws JsonGenerationException, JsonMappingException, IOException{
IronRunId Id = new IronRunId("RunObject", "Runid1", 4);
Map<String, String> aspects = new HashMap<String, String>();
aspects.put("aspectskey1", "aspectsValue1");
aspects.put("aspectskey2", "aspectsValue2");
aspects.put("aspectskey3", "aspectsValue3");
String anotherString = "anotherString";
long time = 1L;
Wrapper objectWrapper = new Wrapper();
ObjectMapper objectMapper = new ObjectMapper();
objectWrapper.setIronRunId(Id);
objectWrapper.setTime(time);
objectWrapper.setAnotherString(anotherString);
objectWrapper.setAspects(aspects);
Map<String, Wrapper> map = new HashMap<String, Wrapper>();
map.put("theWrapper", objectWrapper);
String json = objectMapper.writeValueAsString(map);
Map<String, Wrapper> map1 = objectMapper.readValue(json, new TypeReference<Map<String, Wrapper>>() {});
Wrapper wrapper = map1.get("theWrapper");
System.out.println("run id : " + wrapper.getIronRunId().toString());
System.out.println("time : " + wrapper.getTime());
System.out.println("aspects : " + wrapper.getAspects().toString());
System.out.println("anotherString : " + wrapper.getAnotherString());
}
new TypeReference<Map<String, Object>> is too generic. It is equivalent Map or "untyped" Map mentioned in Data Binding With Generics. The only way for you to deserialize different datatypes in a map or collection is to use TypeFactory.parametricType