I'm writing an Android app for work that shows the status of our phone lines, but thats neither here nor there.
I make a call to one of our servers and get returned JSON text of the status. I then parse this putting each line into a SortedMap (TreeMap) with the Key being the name of the line and my own class as the value (which holds status and other details).
This all works fine.
When the app runs it should then show each line and the info I have retrieved, but nothing gets updated.
The JSON is returned and added to the Map correctly.
This is a snapshot of the code that isn't working. I simply iterate through the map and depending on the value of key update the relevant TextView. The problem I am having is that when it gets to the IF statement that matches it never runs that code. It skips it as if values don't match.
I can't see any errors. Is this the only way to do this as I know you can't use Switch..Case etc?
Can anyone see my error? I've been coding on Android for 1 week now so its probably a newbie error!!
Thanks
Neil
Iterator iterator = mapLines.entrySet().iterator();
while(iterator.hasNext())
{
// key=value separator this by Map.Entry to get key and value
Map.Entry<String, Status> mapEntry = (Map.Entry<String, Status>)iterator.next();
// getKey is used to get key of Map
String key = (String)mapEntry.getKey();
// getValue is used to get value of key in Map
Status value = (Status)mapEntry.getValue();
if(key == "Ski")
{
TextView tvStatus = (TextView)findViewById(R.id.SkiStatus);
tvStatus.setText(value.Status);
}
else if(key == "Cruise")
{
TextView tvStatus = (TextView)findViewById(R.id.CruiseStatus);
tvStatus.setText(value.Status);
}
else if(key == "Villas")
{
TextView tvStatus = (TextView)findViewById(R.id.VillasStatus);
tvStatus.setText(value.Status);
}
}
You must use equals() to compare String objects in Java. Otherwise you just compare if the two objects are the same instance of the String class and don't compare their actual content:
if (key.equals("Ski")) {
...
}
Or, to avoid a NullPointerException if key might be null:
if ("Ski".equals(key)) {
...
}
I prefer to use maps in this case because they eliminate the need for duplicated code and long if else constructs. I don't know where in your code this snippet occurs so this may not apply in your case but just to mention it.
Use a Map to get the correct resource for your String and set the status.
The code would look something like this:
First initialize the map:
Map<String, Integer> textViews = new HashMap<String, Integer>();
textViews.put("Ski", R.id.Ski);
textViews.put("Cruise", R.id.Cruise);
textViews.put("Villas", R.id.Villas);
Then retrieve the correct id and set the text:
((TextView) findViewById(textViews.get(key))).setText(status);
This will reduce the big if else construct a lot and adding a textview will be as easy as changing the map.
checking key with the string literal "Ski", you can use like below . This will prevent nullpointer exception.
if ("Ski".equals(key))
{
...
}
Related
I'm writing a simple skill similart to the java airplane facts sample and I have two strange behaviours:
1) the same code in one intent works correctly, but in another causes an error;
2) I can't remove an element from a public static List!
I will try to explain better with a very close example.
I have two Intents that we can call:
- ActionIntent;
- StopIntent.
The first intent retrieves a list (of type List) retrieved from a class Constants and returns an attribute of a random CustomObject --
this works correctly.
Then it should set the object to Session Attributes and remove it from the list, because the next time the response should be a second attribute of the last CustomObject plus the first attribute of the new CustomObject. Does it make sense?
Here is the code:
// this row works correctly on the other intent
Map<String, Object> sessionAttributes = input.getAttributesManager().getSessionAttributes();
CustomObject last=(sessionAttributes.get("last")!=null) ? (CustomObject)sessionAttributes.get("last") : null;
List<CustomObject> allObjects = MAPPER.convertValue(Constants.getAllObjects(), List.class);
int index = new Random().nextInt(tutti.size());
CustomObject new = allObjects.get(index);
// a simple method that contains allObjects.remove(index) because it didn't work here but also this cause an error
Constants.removeCustomObjectFromList(index);
sessionAttributes.put("ultimoNome", nuovoNome);
String title = Constants.SKILL_TITLE;
String primaryText =new.getTrue();
String secondaryText =(last!=null) ?last.getFalse() : "";
String speechText = "" + secondaryText + " "+primaryText + "?";
return input.getResponseBuilder()
.withSpeech(speechText)
.withSimpleCard(title, primaryText)
.withReprompt(speechText)
.build();
If I comment out the rows linked to the sessionAttribute and the Constants.removeCustomObjectFromList it works correctly but, as I said, the reference to sessionAttribute works correctly in another intent and I must remove CustomObjects from my initial list because the user should listen two time the same thing!
Could someone tell me where to find good info on this subject?
https://ask-sdk-for-nodejs.readthedocs.io/en/latest/Managing-Attributes.html
Above is the official docs. It can be a bit difficult to understand a couple things in there due to lack of extensive explanation, but for the most part everything you need is there. As for your issue, I don't know if this is the only cause, but I don't think getAttributesManager() is a function, unless that's something you've defined. Your code:
Map<String, Object> sessionAttributes = input.getAttributesManager().getSessionAttributes();
Can you try:
Map<String, Object> sessionAttributes = input.attributesManager.getSessionAttributes();
instead?
I am reading a database and filling up a hashtable, my key is a string for example "1-1", which is a string and it is unique (I checked many times) and my value is an object that has other objects as attributes. The problem is that when I am filling my hashtable, some of my entries end up with wrong values for one of the attributes namely MethodTrace.Method.Owner.DeveloperGold.
The value is set correctly in the first iteration but when I reprint the same value in the next iteration or at the end of the loop, I end up with the wrong value
System.out.println("WE ARW IN THE LOOP "+methodtraceHashMap.get("1-1"));
For some reason, it feels like the last value that was set in
MethodTrace.Method.Owner.DeveloperGold = myresults.getString("ownergold");
gets assigned and put into the value in the hashmap corresponding to the entry with the key "1-1". I am not really sure how to fix this.
ResultSet myresults = st.executeQuery("SELECT traces.* from traces");
while (myresults.next()) {
MethodTrace MethodTrace = new MethodTrace();
Method method= new Method();
Requirement requirement= new Requirement();
requirement=RequirementHashMap.get(myresults.getString("requirementid"));
method =
MethodHashMap.get(myresults.getString("methodid"));
MethodTrace.setMethod(method);
MethodTrace.setRequirement(requirement);
//checking whether the method is present in the
// superclasses
MethodTrace.setGold(myresults.getString("goldfinal"));
String reqMethod=MethodTrace.Requirement.ID+"-
"+MethodTrace.Method.ID;
String reqClass=MethodTrace.Requirement.ID+"-
"+MethodTrace.Method.Owner.ID;
MethodTrace.Method.Owner.DeveloperGold=
myresults.getString("ownergold");
System.out.println(reqMethod+"-");
System.out.println(MethodTrace.Method.Owner.DeveloperGold);
methodtraceHashMap.put(reqMethod, MethodTrace);
System.out.println("WE ARW IN THE LOOP
"+methodtraceHashMap.get("1-1"));
}
Try this and print the hashmap and see if you still have the overwriting issue
methodtraceHashMap.put(reqMethod+"_"+System.currentTimeMillis(), MethodTrace);
System.out.println("WE ARW IN THE LOOP
"+methodtraceHashMap.get("1-1"));
I think you (or the library you are using) overridden the hashCode of the object you want to store in the HashMap. To fix this issue you should use a Map that isn's searching (and inserting) elements by it's hash code
I recommend you debug your code with following temporary correction:
if (methodtraceHashMap.put(reqMethod, MethodTrace) != null)
throw new RuntimeException("key '" + reqMethod + "' duplication");
As you use String as a hash map key, so you do not have problem with custom hashCode. I am sure, your key is unique and you have to find out what key exactly and then fix it.
Based on this example here, this works. Have tried the same on my dataset.
Sample Dataset:
OBSERVATION;2474472;137176;
OBSERVATION;2474473;137176;
OBSERVATION;2474474;137176;
OBSERVATION;2474475;137177;
Consider each line as string, my Mapper output is:
key-> string[2], value-> string.
My Partitioner code:
#Override
public int getPartition(Text key, Text value, int reducersDefined) {
String keyStr = key.toString();
if(keyStr == "137176") {
return 0;
} else {
return 1 % reducersDefined;
}
}
In my data set most id's are 137176. Reducer declared -2. I expect two output files, one for 137176 and second for remaining Id's. I'm getting two output files but, Id's evenly distributed on both the output files. What's going wrong in my program?
Explicitly set in the Driver method that you want to use your custom Partitioner, by using: job.setPartitionerClass(YourPartitioner.class);. If you don't do that, the default HashPartitioner is used.
Change String comparison method from == to .equals(). i.e., change if(keyStr == "137176") { to if(keyStr.equals("137176")) {.
To save some time, perhaps it will be faster to declare a new Text variable at the beginning of the partitioner, like that: Text KEY = new Text("137176"); and then, without converting your input key to String every time, just compare it with the KEY variable (again using the equals() method). But perhaps those are equivalent. So, what I suggest is:
Text KEY = new Text("137176");
#Override
public int getPartition(Text key, Text value, int reducersDefined) {
return key.equals(KEY) ? 0 : 1 % reducersDefined;
}
Another suggestion, if the network load is heavy, parse the map output key as VIntWritable and change the Partitioner accordingly.
I need to read a flag to validate if I'll send or not an email, this flag is on a LinkedHashMap, so I'm trying to go over it looking for an ID, then I'll have to ask if is true or false, and I'm trying this:
while(iterator.hasNext()){
LinkedHashMap<String, Object> fileMap = (LinkedHashMap<String, Object>) iterator.next();
userid = (Long)fileMap.get("USERID");
file.findAllFiles(userid);
if(file.findAllFiles(userid).contains(haveFiles = true)){
//send email
}else{
//do something
}
}
Is it correct?
I think your if expression has a logical error.
haveFiles = true
will always return true, reducing your expression to :
file.findAllFiles(userid).contains(true)
since (haveFiles = true) assigns the value true to the variable haveFiles.
You should rather be doing something on the following lines :
Map<Flag, Boolean> keyValueMap = file.findAllFiles(userid)
if(keyValueMap.contains(Flag.HAVE_FILES) == true){
//send email
}else{
//do something
}
..asuming you the file.findAllFiles() returns a map object with flags and their boolean status and Flag is an enum containing all the supported flags.
The expression
(keyValueMap.contains(Flag.HAVE_FILES) == true)
will evaluate to true only when keyValueMap contains an entry for Flag.HAVE_FILES and the value is true.
Assuming it works up to the point of:
if(file.findAllFiles(userid).contains(haveFiles = true))
Then I think the issue is in that condition itself. What you have written is roughly equivalent of writing
??? haveFiles = true;
if(file.findAllFiles(userid).contains(haveFiles))
(where ??? can be either Object, Boolean or boolean, don't know from your code snapshot)
I bet what you might want to do is something like
Boolean haveFiles = file.findAllFiles(userid).get("haveFiles");
if (Boolean.TRUE.equals(haveFiles) {
What you have done calls the contains method which receives any Object and returns true if that object is among the values of the map. You probably don't want that, I guess what you want to do is to retrieve the value associated to the "haveFiles" key into the map, for that you have to use the get method.
PS: Also, if file.findAllFiles(userid) method is truly calling some DB stuff you might want to invoke it only once (the first time looks totally unnecesary to me).
I'm making a game, and i want the controls to be editable. well, i've got that part down, but they are being read and changed in a .txt file. that is the way i wanted it to work for now. the values are stored as the key value (ie. KeyEvent.VK_W is equal to 83, so the value for the line is 83). I also have it reading the values and saving them to a String array variable in my core class. In my key event class, the one that handles the pushing of the keys, i have it refering to the array to check if a command key was pushed. i'm continuously getting this error: case expressions must be constant expressions when i try it. here is the WRONG code:
switch(key){
case Integer.parseInt(commands[1]):
...
break;
}
and i get that error. the value of commands[1] is 83. it is the value for "W". here is my declaration of the variable:
for (int i = 0; i < commands.length; i++) {
commands[i] = io.readSpecificLine(FILES.controlsFileFinalDir,
i + 1);
}
and if i have it print out every value, it does work. i've tried making the array final but that didnt work. i've run across the solution before, about 2 years ago, but i cant find it again. does anyone have any ideas on how to fix this? thanks in advance!
As the compiler says, the case expressions must be constant expressions. You can't use an array element as a case expression. You can simply use an if/else if/else clause instead.
You can't use non-constant expressions in case statements. An alternative approach is to build a map from values to the actions. So instead of this (which doesn't actually make any sense to me):
switch (key) {
case Integer.parseInt(commands[1]):
// action 1
break;
// other cases...
default:
// default action
}
You can do something like this:
static Map<Integer, Runnable> keyMap = new HashMap<Integer, Runnable>();
static {
keyMap.put(83, new Runnable() {
#Override
public void run() {
// actions for code 83
}
});
. . .
}
(If it makes more sense, this could also be done on a per-instance basis instead of as a static map.) Then later:
Runnable action = keyMap.get(Integer.parseInt(commands[1]));
if (action != null) {
action.run();
} else {
// default action
}
If you need to pass variables to your actions, you can define your own interface instead of using Runnable for the actions.