Errors when checking if HashMap key exists - java

I am currently using a hashmap to store information about a Current Account.
Here is what I have in one method:
HashMap<String, Account> account = new HashMap<String, Account>();
if (Account.validateID(accountID)) {
System.out.println("Account ID added");
Account a = new Account(cl,accountID, sortCode, 0);
account.put(accountID, a); //add to HashMap
}
This seems to work fine. Then in another method I have:
public void enterTransaction()
{
String tAccountID = JOptionPane.showInputDialog(this,
"Enter valid accountID", "Add Account", 0);
System.out.println("Check if accountID exists: " + account.containsKey(tAccountID)); //testing if accountID exists - currently not working
Date currentDate = new Date();
System.out.println("Date and time of transaction: " + currentDate); //prints the date and time of transaction
}
Basically, i'm trying to make it so that when I go to enter a transaction, it checks that the AccountID that is entered for the transaction is equal to the AccountID from the HashMap (the key).
I tried using line 6 of the enterTransaction() to check whether it exists. However, it doesn't seem to work and always says "false" even when I know i have typed in the same accountID both times. I have also tried using this statement:
System.out.println(account.get(accountID));
This seems to give me "Account#cb1edc" ?
Sorry about the long question, it's a simple question really just thought i'd give you all the information I could. Thanks.

That is the correct behavior.
account.get(accountID) returns an Account object, which is being printed from the JVM memory dump.
To get some legible output, the Account class needs a toString method that returns a String with useful information.
When you try to print an object to the console, the JVM automatically searches for a toString method and uses that to stringify the object (make it humanly readable), if it cant find that method for the object it prints out the JVM's internal memory id for that object which looks a bit like garbage. Try this:
public String toString() {
return "This is account " + this.id; // or something like this
}

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

Hashtable returning null but object key is present

EDIT: FML! MY implementation of hashcode had a lowercase c. -.-
I've been trying to learn TDD and have been following the 'By Example' book by Kent Beck; it's very good!
However, I can't seem progress because a value is returning null when I access a hashtable. I've run a debug session and the object with the value is clearly there yet the result is null.
The code to build and access is:
public void addRate(String from, String to, int rate){
this.rates.put(new Pair(from, to), new Integer(rate));
}
from and to are "GBP" and "USD". Also verified by debug.
Test case calling the above:
#Test
public void testreduceMoneyDifferentCurrency(){
Bank bank = new Bank();
bank.addRate("GBP", "USD", 2);
Money result = bank.reduce(Money.gbpound(2), "USD");
assertEquals(Money.dollar(1), result);
}
The reduce method in bank calls the method rate:
public Money reduce(Bank bank, String to){
int rate = bank.rate(this.currency, to);
return new Money(this.amount / rate, to);
}
Which is where the issue is:
public int rate(String from, String to){
if (from.equals(to)) return 1;
Integer rate = (Integer) this.rates.get(new Pair(from, to));
return rate.intValue();
}
The first line copes with USD -> USD conversions etc.
The Pair object is 2 strings built to be used as a key.
I've not used has tables a great deal but I can't see what the issue is, I know for certain that the values are in the hashtable but 'rate' is always returning a null value.
I can't see the wood for the trees. :) Could someone point me in the right direction please?
I think the problem is in the Pair method.
When you do this:
this.rates.get(new Pair(from, to));
you are creating a new instance of Pair, which is not the same as the one you've put into the map in the addRate method.
If you want the code to work correctly, you either have to use the same instance of Pair class or correctly implement equals and hashCode method on Pair class.
Here's a bit deeper insight into the inner working on HashMap and what you have to do to make it work: https://stackoverflow.com/a/6493946/2266098
Java keeps the reference of objects. So when you are trying to do this
this.rates.get(new Pair(from, to));
you are basically creating a new instance of Pair which does not exists as a key in your HashMap.

Filter for duplicate values.

I am trying to add a filter to check for duplicate values that a user might input. I am not sure where I am going going wrong in my query.
My query doesnot enter the loop to check if the name already exists.
I am fairly new to google-could. If someone can tell me on how I can fix my problem or if there is a better solution.
else if ( commandEls[0].equals( "add_director" ) ) {
String name = commandEls[1];
String gender = commandEls[2];
String date_of_birth = commandEls[3];
boolean duplicate = false;
//add a director record with the given fields to the datastore, don't forget to check for duplicates
Entity addDirectorEntity = new Entity("Director");
// check if the entity already exits
// if !duplicate add, else "Already exisits"
Query directorExists = new Query("Movies");
// Director Name is the primary key
directorExists.addFilter("directorName",Query.FilterOperator.EQUAL, name);
System.out.print(name);
PreparedQuery preparedDirectorQuery = datastore.prepare(directorExists);
System.out.print("outside");
for(Entity directorResult : preparedDirectorQuery.asIterable()){
// result already exists in the database
String dName = (String) directorResult.getProperty(name);
System.out.print(dName);
System.out.print("finish");
duplicate = true;
}
if(!duplicate){
addDirectorEntity.setProperty("directorName",name);
addDirectorEntity.setProperty("directorGender",gender);
addDirectorEntity.setProperty("directorDOB",date_of_birth);
try{
datastore.put(addDirectorEntity);
results = "Command executed successfully!";
}
catch(Exception e){
results = "Error";
}
}
else {
results = "Director already exists!";
}
}
Non-ancestor queries (like the one in your example) are eventually consistent, so they cannot reliably detect duplicate property values. Ancestor queries are fully consistent, but they require structuring your data using entity groups, and that comes at the cost of write throughput.
If the directorName property in your example is truly unique, you could use it as the name in the key of your Director entities. Then, when you are inserting a new Director entity, you can first check if it already exists (inside of a transaction).
There's no general, built-in way in Datastore to ensure the uniqueness of a property value. This related feature request contains discussion of some possible strategies for approximating a uniqueness constraint.
I'd also recommend reading up on queries and consistency in the Datastore.
That is a valid thing to do but i figured out my problem.
I am making an Entity for Director where as That should be for movies.

Java: Code Understanding

I'm new to JAVA, but I know Objective-C. I have to write a server side Custom Code and I'm having trouble with the code below:
/**
* This example will show a user how to write a custom code method
* with two parameters that updates the specified object in their schema
* when given a unique ID and a `year` field on which to update.
*/
public class UpdateObject implements CustomCodeMethod {
#Override
public String getMethodName() {
return "CRUD_Update";
}
#Override
public List<String> getParams() {
return Arrays.asList("car_ID","year");
}
#Override
public ResponseToProcess execute(ProcessedAPIRequest request, SDKServiceProvider serviceProvider) {
String carID = "";
String year = "";
LoggerService logger = serviceProvider.getLoggerService(UpdateObject.class);
logger.debug(request.getBody());
Map<String, String> errMap = new HashMap<String, String>();
/* The following try/catch block shows how to properly fetch parameters for PUT/POST operations
* from the JSON request body
*/
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(request.getBody());
JSONObject jsonObject = (JSONObject) obj;
// Fetch the values passed in by the user from the body of JSON
carID = (String) jsonObject.get("car_ID");
year = (String) jsonObject.get("year");
//Q1: This is assigning the values to fields in the fetched Object?
} catch (ParseException pe) {
logger.error(pe.getMessage(), pe);
return Util.badRequestResponse(errMap, pe.getMessage());
}
if (Util.hasNulls(year, carID)){
return Util.badRequestResponse(errMap);
}
//Q2: Is this creating a new HashMap? If so, why is there a need?
Map<String, SMValue> feedback = new HashMap<String, SMValue>();
//Q3: This is taking the key "updated year" and assigning a value (year)? Why?
feedback.put("updated year", new SMInt(Long.parseLong(year)));
DataService ds = serviceProvider.getDataService();
List<SMUpdate> update = new ArrayList<SMUpdate>();
/* Create the changes in the form of an Update that you'd like to apply to the object
* In this case I want to make changes to year by overriding existing values with user input
*/
update.add(new SMSet("year", new SMInt(Long.parseLong(year))));
SMObject result;
try {
// Remember that the primary key in this car schema is `car_id`
//Q4: If the Object is updated earlier with update.add... What is the code below doing?
result = ds.updateObject("car", new SMString(carID), update);
//Q5: What's the need for the code below?
feedback.put("updated object", result);
} catch (InvalidSchemaException ise) {
return Util.internalErrorResponse("invalid_schema", ise, errMap); // http 500 - internal server error
} catch (DatastoreException dse) {
return Util.internalErrorResponse("datastore_exception", dse, errMap); // http 500 - internal server error
}
return new ResponseToProcess(HttpURLConnection.HTTP_OK, feedback);
}
}
Q1: Code below is assigning the values to fields in the fetched Object?
carID = (String) jsonObject.get("car_ID");
year = (String) jsonObject.get("year");
Q2: Is this creating a new HashMap? If so, why is there a need?
Map<String, SMValue> feedback = new HashMap<String, SMValue>();
Q3: This is taking the key "updated year" and assigning a value (year)? Why?
feedback.put("updated year", new SMInt(Long.parseLong(year)));
Q4: If the Object is updated earlier with update.add... What is the code below doing?
result = ds.updateObject("car", new SMString(carID), update);
Q5: What's the code below doing?
feedback.put("updated object", result);
Original Code
SMSet
SMInt
Q1: They read from the fetched JSON object and stores the values of the fields car_ID and year in two local variables with the same names.
Q2: Yes. The feedback seems to be a map that will be sent back to the client as JSON
Q3: It stores the value read into the local variable 'year' (as described earlier) in the newly created hashmap 'feedback'
Q4: Not sure, I assume the ds object is some sort of database. If so it looks like it takes the updated values stored in the hashmap 'update' and pushes it to the database.
Q5: It stores the "result" object under the key "updated object" in the feedback hashmap.
Hope this helps :)
Q1
No, it does not appear to be setting a class member variable, but rather a variable local to the execute() method. As soon as the method returns, those local vars are cleaned up by the GC. Well, not really, but they are now subject to GC, but that's getting really technical.
Q2
Yes, you are creating a HashMap and putting it's reference into a Map. Map is an interface, and it's good practice in Java to reference thing like this. This way you are not tying your code to a specific implementation. I believe in Objective-C they are know as Prototypes???
Q3
I am not sure why they are doing this. I assume somewhere in the code the feedback Map is used, and that value is plucked back out. Think of Maps as an NSDictionary. It looks like "year" is a String, so they use Long.parseLong() to convert it. Not sure what SMInt is...from the name it looks like a custom class that represents a "small int"???
Q4
I don't know what DataService is, but I have to guess its some sort of service the reads/write data??? From the method, I am guessing its calling the service to update the values you just changed.
Q5
Again, feedback is a Map...it's putting result in the "updated object" key of that map.

Best Way to Append Integers to End of Username?

I'm working on a Java class that gets parameters from an "Account Request" form (like 'First Name', 'Last Name', 'email', etc.).
The Java class first gets the parameters from the form. It then initializes a user name with the first and last name strings like so:
String userName = firstName.substring(0,1).toLowerCase() + lastName.toLowerCase();
For example, the username for "Jake Smith" would be jsmith.
Afterwards, it checks to see if this 'userName' exists in the database. Obviously, "Jake Smith" and "John Smith" would create identical user names, "jsmith". To account for this, I'd just like to append numbers, starting with 1, to any matching user names.
How can I append a unique number at the end of each and every conflicting username (starting with 1 and incremented by 1 for each additional conflict)?
Obviously, a more elegant solution would be to allow the user to specify their user name, but this is how the mock client wants the project to be completed.
Thank you!
You could use String.format, something like:
String.format("%s%d", username, i++);
A "dumb" solution, but if it's just for tests...
private String getUsername(){
String userName = firstName.substring(0,1).toLowerCase() + lastName.toLowerCase();
int i=1;
while(usernameExists(userName)){
userName = userName.replaceAll("\\d+$","") + i++;
}
return userName;
}
Considering that userName don't have digits in the end.
Use a StringBuilder to construct the new string and StringBuilder#toString to obtain it.
Here's a simple method that uses a Map to keep track of ids.
class UniqueUsername {
private static Map<String, Integer> ids = new HashMap<String, Integer>();
public static String getUniqueUsername(String username) {
if (!ids.containsKey(username)) {
ids.put(username, new Integer(0));
return username;
}
ids.put(username, ids.get(username)+1);
return username + ids.get(username);
}
}
If conflicts are unlikely then you could just loop until unique, staring at 1 and adding 1 each time
For example:
i=0;
String usernameToTry=username;
while (notUnique(usernameToTry)) {
i++;
usernameToTry=username+i;
}
If conflicts are likely then you may find this approach unsatisfactory because of the performance penalty of hitting the database (to check if unique) for every iteration of the loop. For example, if you have jsmith100 already then you don't want to check 100 times before coming up with jsmith101.

Categories