Hashmap value gets modfied while inserting values into the hashmap - java

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.

Related

How to detect a string within an ArrayList with a for each loop?

public String searchNumber(String name){
String result = "";
for(Person search: person){
if(search.getName().contains(name)){
result += search.getNumber();
}
else{
result = " number not known ";
}
}
return result;
}
Looking for some advice here on how to fix this problem I am having. This is a method which I expect to use my getName method to see if the local instance (name) is within the ArrayList. However, I am only getting the latter result to display only, saying "number not known." My step-by-step process goes like this: I create an instance of Person (search), access the getName method, access the contains method since it is originally a String method, and then check to see if the local instance is within the arrayList. If my logic is incorrect, please correct me. Also, does accessing the person array prevent me from using a String type in my for-each loop, since it is a Person object? I tried do this with a String type, but could not continue further since I could not convert to a String within the for-each loop.
Here's a breakdown of your current code:
You consider every object in the person list. If that person's name matches the parameter, you get the number from it. Otherwise, you set result to the error message. Note that the otherwise clause is applied for EACH person, instead of at the end if NOBODY was found to have the same name. That is, even if you find the right person and assign result to their number, if the next person isn't correct then you overwrite result to the error message again.
To make sure the error message is only assigned once and only if NOBODY is found, you need to check whether that is true after going through everyone (since you can't know if nobody is found before checking everyone!). The trick now is to find some clause which is always true when nobody was found. But that can just be if result was never modified. That is, you can set result to the default value at declaration, then only modify it to a number if the right person was found. Also, I am assuming that only one person should be found and you don't want to actually concatenate the numbers together (which is what you are doing by using +=). That said, try this:
public String searchNumber(String name){
for (Person search: person){
if (search.getName().contains(name)){
return search.getNumber();
}
}
return " number not known ";
}
Basically you can just return after finding your record
String notFound = " number not known ";
for(Person search: person){
if(search.getName().contains(name)){
return search.getNumber();
}
}
return notFound;
String result = null;
for(Person search: person){
if(search.getName().contains(name)){
result += search.getNumber();
}
}
if(result == null){
result = "number not known ";
}
return result;
Since there is no way to tell the last element in for-in loop, so the alternative is basing on result == null

How to append two value to one key using Redis Spring Data

I using redis caching my project but i have a problem. I had model student and write method put it to redis.First method i write findStudent one week and put it to cache.
public void findStudentOneWeek(List<Student> students1) {
redistemplate.opsForHash().put("Student", student.getId(), List<Customers>);
}
Second method I write findStudent one day.
public void findStudentOneDay(List<Student> students2) {
redistemplate.opsForHash().put("Student", student.getId(), List<Customers>);
}
But i want total user from 8 day. It mean i want hold one key Student but new value equal total value method findStudentOneWeek + total value method findStudentOneDay. But i don't now how to do. I can't find method working it. I know method put from redis but it remove old value and save new value. I don't want it. I want value total.
Firstly, I assume a typo, where List<Customers> should be List<Students> student:
redistemplate.opsForHash().put("Student", student.getId(), List<Students> students);
Spring Data class HashOperations works on the similar principle as HashMap. Both allow you to get the value by the key (and the hash key in case of HashOperations). Read the current value List<Customers> and put them with a new value to the template.
List<Students> students = redistemplate.opsForHash().get("Student", student.getId());
students2.addAll(students);
redistemplate.opsForHash().put("Student", student.getId(), students2);

How can I use an int as a HashMap key?

I'm trying to use a HashMap to store instances of a simple class, called User. I'm using Integer as the key type, as I want to look up entries by user id, but I keep getting NullPointerException when I try to save a new entry.
Here's the snippet of code that's causing the problem:
Integer i = Integer.valueOf(id);
User bob = new User(id, seq, packet.getPort(), packet.getAddress());
if (i == null || bob == null) {
System.out.println("Null object.");
}
users.put(i, bob);
The values used in the User constructor have already been set, and the debug statement I added is never printed. Nevertheless, an exception is thrown when I try to call users.put(i, bob);. Is there another way to use an int as a key?
Edit: I'm dumb and didn't initialize the HashMap itself.
I would guess that users (your HashMap) is null

Java is not assigning values to my variables correctly, with linked lists

public void returnRental(Customer cust){
Rental toDelete = null; //Rental to be removed from list.
LinkedList<Video> toReturn = null; //List of videos to be added to inventory.
//Find appropriate rental according to customer name.
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
}
}
here is the snippet of code that is giving me problems. I've debugged it in eclipse quite a bit which ended up just confusing me more. It hits the if, and passes the condition. But once it gets to assigning values to "toReturn" it assigns it an empty list with size 0. Where as I check my rentals Linked list and the correct value are there, but for some reason it is not getting assigned to my variables correctly :( The same happens to "toDelete" but this isn't a list, it is one instance of my class Rental. (The linked list is a list of rentals, which contains a linked list of videos)
No errors are thrown...
Its a little difficult to explain, if you need more information please let me know and i'll clarify.
I'm at a loss, possibly because I'm not iterating through my linked list correctly?
Replace
if (cust.getName() == rentals.get(i).getRentee().getName()){
by
if (cust.getName().equals(rentals.get(i).getRentee().getName())){
You can't compare strings with == (except if your algorithm can ensure this is the same instance, which is almost never the case).
But the missing equals is not the only bug. It may be inside getRented() or elsewhere (you don't show what you do with toReturn and toDelete, so it's not clear if you don't have problems here).
Now, to go on chasing your bugs, you should either
debug, and put a breakpoint in your loop to check the state of rentals.get(i) and the execution at this point
if you can't debug, put a lot of System.println, so that you know what you have...
I've upvoted dystroy's answer because incorrect string comparison is always wrong.
But because that would fail differently (customer names not matching rentee names), I'm wondering if your issue is really caused by either of the following:
a problem in getRented(); or
cust having a null name on call, which would match a Rentee with a null name.
Possibly, your if condition is being hit more than once. First of all, check if this is actually happening. If so, check your logic and determine if you want to stop at the first occurence or at the last (this case seems to be the latter).
If you want to stop at the first occurence, break the iteration:
for(int i = 0; i < rentals.size(); i++){
if(cust.getName() == rentals.get(i).getRentee().getName()){
toReturn = rentals.get(i).getRented();
toDelete = rentals.get(i);
break;
}
}
for(int i = 0; i < rentals.size(); i++){
if(cust.getName().equals( rentals.get(i).getRentee().getName())){
toReturn.addAll(rentals.get(i).getRented());
//assumming it returns the list of Video object
toDelete = rentals.get(i);
}
}

ANDROID: If...Else as Switch on String

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))
{
...
}

Categories