I'm trying to create a program that keeps track of a bunch of different Strings, and "ties them together" with the current user's entered name (another String), meaning every person should have their own wallets. I tried to do this using a Map inside another Map, but this is where my brain overloads. How do I tie every wallet to the correct name and then display all of that? The comment in my code gives a good example of it. Here is what I have so far:
Scanner sysin = new Scanner(System.in);
boolean firstTime = true;
Map<String, Set<Long>> walletTracker = new HashMap<String, Set<Long>>();
Map<String, Map<String, Set<Long>>> nameTracker = new HashMap<String, Map<String, Set<Long>>>();
if(!firstTime) {
/* Here it should display every entered name, wallet and time of deposit, like this:
Jack:
JacksWallet:
[12345], [123456], [1234567]
JacksOtherWallet:
[123], [1234]
Jonathan:
JonsWallet:
[12345678]
*/
}
for(int i = 0; i < 1;) {
System.out.print("Enter your name: ");
String name = sysin.nextLine();
System.out.print("Please enter a wallet name: ");
String wallet = sysin.nextLine();
Set<Long> deposits = walletTracker.getOrDefault(name, new HashSet<>());
deposits.add(System.currentTimeMillis());
walletTracker.put(wallet, deposits);
nameTracker.put(name, walletTracker);
System.out.println("You successfully withdrew money from "+ wallet +". Press enter to continue...");
firstTime = false;
String enter = sysin.nextLine();
}
Here's what I found & noticed:
The if(!firstTime) {} block should be within the for loop, so that it actually prints on every iteration.
You attempt to use walletTracker.getOrDefault(name, new HashSet<>());, but the name variable is not the correct variable to use here. You should be using the wallet input variable.
Here is my "print it out" code, that matches your recommended formatting:
nameTracker.forEach((name, wallet) -> {
System.out.println(name);
wallet.forEach((walletName, dates) -> {
System.out.printf("\t%s\n\t\t%s\n",
walletName, Arrays.toString(dates.toArray(new Long[0])));
});
});
Outside of this, the code you used to actually populate the map(s) is correct.
#rzwitserloot Made some good points about using OOP to your advantage, and I would recommend those suggestions as well.
Set<Long> deposits = walletTracker.getOrDefault(name, new HashSet<>());
This returns new HashSet<>() if there is no mapping for name but it does not add that to the map. What you want is .computeIfAbsent, which will just return the mapping that goes with name, but if it is not there at all, it evaluates your lambda and then adds that to the map and then returns that:
Set<Long> deposits = walletTracker.computeIfAbsent(name, k -> new HashSet<>());
That's 'lambda' syntax - you don't write an expression that resolves to a new hashset, you write an expression that resolves to a function that produces a new hashset when provided with the key (which we don't need here, and is equal to name anyway).
Java-esque strategy here is to make a Wallet class at least. In general, once you start putting <> inside `<>, especially if you're 3 levels deep, stop, and start writing classes instead.
That should be a Map<String, Wallet> and a Map<String, Person> or whatnot.
Related
Right now I'm creating a bankApp and I don't have an idea how can I assign e.g. string name; double balance; etc. to a right one int PIN;. There is gonna be many accounts with different PINs and different values assigned to it . I tried making many objects :
perInfo card1 = new perInfo();
card1.PIN = 1994;
card1.balance = 24.68;
card1.isValid = true;
perInfo karta2 = new perInfo();
card2.PIN = 2002;
card2.balance = 522.2;
card2.isValid = false;
but I think it's too much work to do and it'll worsen performance of the app. I also tried making a list
public bApp(int pin, double balance){
this.pin = pin;
this.balance = balance;}
List<bApp> pass = new ArrayList<>();
pass.add(new bApp(1994, 568.45));
pass.add(new bApp(2002, 13866.24));
but it didn't work ,because I couldn't call the PIN to check that if user has provided the right one PIN . Arrays are also not suited for this.
You could use a HashMap for this and use the pin as a key and store the object in the HashMap. This would allow you to access each card using only the pin. However, this would not allow for duplicate pins. I would recommend that you reference each account by a unique ID and check the pin within the object itself.
HashMap<Integer, Account> accounts = new HashMap<Integer, Account>();
accounts.put(12345678, new Account(1994, 568.4));
You can then get the account using the unique ID and check if the pin is correct.
Account acc = accounts.get(uniqueID);
if(acc.pin == enteredPin){
//Whatever you need to do
}
The data structure you are looking for is a Map. Take a look at HashMap and you'll want to key off of whatever value you are using to lookup.
For example if you wanted to lookup a user by pin:
Map<Integer, bApp> passes = new HashMap<>();
passes.put(1994, new bApp(1994, 568.45));
passes.put(2002, new bApp(2002, 13866.24));
I think it would be simpler to just have an array of the different cards, with each pin being set to the array address:
bApp[] cards = new bApp[NUMBER_OF_CARDS];
cards[0] = new bApp(0, 568.45);
// ...
cards[2002] = new bApp(2002, 13866.24);
I'm sorry if this is a very obvious question, I guess I simply don't know the proper vocabulary to use to find the answer. My question is: Say I instantiate several objects, and each object has a unique integer that serves as its ID, and I want the user to be able to choose which object to modify by entering the object's ID. How should I go about that?
int ID;
Scanner keyboard = new Scanner(System.in);
Object obj1 = new Object(9897);
Object obj2 = new Object(2817);
System.out.println("Input the ID of the object you wish to modify:");
ID = keyboard.nextInt();
Assume I have a class written so that the objects instantiated in the previous code have their IDs equal to the argument passed to the constructors. Now say in the next line of code I want to change either object 1 or object 2 depending on whether the user inputs 9897 or 2817. How would I go about doing that without using a ton of if statements?
Short answer: you don't. Change your approach, put your instances in a Map<Integer, Object> and then you can look them up by ID.
Map<Integer, Object> map = new HashMap<>();
map.put(9897, new Object());
map.put(2817, new Object());
// ...
int ID = keyboard.nextInt();
Object obj = map.get(ID);
For my program i want to have it so that the user can name the variables a bit like in a game you would name your charecter/world. I looked it up and couldn't find anywhere that said if this is possible and if so how it is done.
As many others have said, you can't dynamically name variables.
You can however make a Map
It would allow you to create any name for a variable such as "MyTestVar" at runtime and use it as a key in that map to whatever you put:
Map<String, String> myMap = new HashMap<String, String>();
String varName = getVariableNameFromUser();
String value = getValueFromUser();
myMap.put(varName, value);
// ... later
String whatVariableDoYouWantTheValueOf = getVarNameFromUser();
String storedValue = myMap.get(whatVariableDoYouWantTheValueOf);
System.out.println("The value for that is: " + storedValue);
What you can do is create a linked list or an arraylist of some type of object that you create. Your object can then have two properties (or more) where one is the name, and the other is the value. You can then search for an object in your list based on the name, and return the value that you want. This will basically accomplish what you're trying to achieve.
You can't get a user to name a variable. All you can do is allow the user to set the variable's value.
I guess what you mean is something like giving Tags or Labels to Objects. "Variable Names" is a missleading wording for that.
After the User typed in the name string for an obj Object, you could for example use a HashMap<String, Object> to store the user input:
Map<String, Object> tagToObjectStore = new HashMap<String, Object>();
String userInput = "any Tag name";
Object somethingToLabel = ... // TODO
tagToObjectStore.put(userInput, somethingToLabel); // store the user input
// later in code...
Object theStoredObject = tagToObjectStore.get(userInput); // get the stored object
Is that what you are looking for?
I was wondering if its possible to store an object into a arraylist where the user wants it. For my program its storing the users data into a cell of their choice via an "account number" but every time I type in a new account number it says that the array isn't big enough basically. Here is my code. If anyone could help that would be appreciated.
ArrayList <Account> account = new ArrayList<Account>();
int accountNumber;
String nCity;
String nState;
String nZipCode;
String nLastName;
String nAddress;
String firstName;
String nAccount;
public void newAccount()
{
Account a = new Account();
a.firstName = JOptionPane.showInputDialog("What's your first name?");
a.nLastName = JOptionPane.showInputDialog("What's your last name?");
a.nAddress = JOptionPane.showInputDialog("What's your current address?");
a.nCity= JOptionPane.showInputDialog("What's your current city?");
a.nState = JOptionPane.showInputDialog("What's your current State?");
a.nZipCode = JOptionPane.showInputDialog("What's your current Zip Code?");
String num = JOptionPane.showInputDialog("What do you want your account number to be?");
accountNumber = Integer.parseInt(num);
account.add(accountNumber, a);
Use a HashMap and use the account number as the key
Map<Integer,Account> account =new Hashmap<Integer,Account>();
account.put(accountNumber,a);
You have created an ArrayList<Account> and you are adding elements into it in the form of key-value pair.
If you want to add that way, you probably need a HashMap: -
Map<Integer, Account> accounts = new HashMap<Integer, Account>();
then, to add entry in it, you can use Map#put() method: -
accounts.put(accountNumber, a);
Agree with the above suggestions about using Map.
Your "array isn't big enough" is simply because you are trying to specify the index of the List while you haven't initialize the indexes yet.
Simply, you are using this method of List:
add(int index, E element)
Inserts the specified element at the specified position in this list.
The keyword is INSERT.
So, imagine if your "accountNumber" is 100, and you don't have the 99 elements before it, trying to insert will make no sense in logic because you are inserting into nowhere.
JavaSE6 API says under this method:
IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
By the way, another solution, if available to you, besides using Map is to have accountNumber as another field of Account, and you can use List now with the single-argument add() method.
I implemented two Hashtable as shown below.
HashMap<Integer,String> streetno=new HashMap<Integer,String>();
streetno.put(1, "Sachin Tendulkar");
streetno.put(2, "Dravid");
streetno.put(3,"Sehwag");
streetno.put(4,"Laxman");
streetno.put(5,"Kohli");
HashMap<String,Integer> streetname=new HashMap<String,Integer>();
streetname.put("Sachin Tendulkar",1);
streetname.put("Dravid",2);
streetname.put("Sehwag",3);
streetname.put("Laxman",4);
streetname.put("Kohli",5);
Iterator itr=streetno.keySet().iterator();
Now I'm asking user for input. If he enters the integer I want to retrieve particular value from the 1st hash table and if user enter the string I want to read the particular integer from 2nd hashtable.
My question is "How can I read the input from the user??" Because I don't know whether user enters the integer or string??
And I also wanted to know Can I retrieve particular value using Iterator depending on the key??
How can I read the input from the user??
Something like
String line = scanner.nextLine();
Because I don't know whether user enters the integer or string??
Try to convert it to an integer
try {
int num = Integer.parseInt(line);
// lookup by number
} catch(NumberFormatException ignored) {
// lookup by string
}
Can I retrieve particular value using Iterator depending on the key??
An Iterator is for iterating, a Map is for looking up by key.
First, you'll need to read the standard input. Handle it first as a String, to simplify.
Scanner scanner=new Scanner(System.in);
String userInput=scanner.nextLine();
Then, try to convert the String to an Integer. If the user typed a number, you'll get the key a the first Map, otherwise, you can asume it's a String key for the second one:
String sName;
Integer iNumber;
try {
iNumber=Integer.parseInt(userInput);
//user intruduced a number, so get the streename
sName=streetno.get(iNumber);
} catch (NumberFormatException e) {
//user introduced a not-numeric String, so get the streetnumber
sName=userInput;
iNumber=streetname.get(sName);
}
You don't need to iterate over the keyset, as the Map.get() method will return you the corresponding value.
finally, don't forget to release the scanner (better in a finally block):
scanner.close();
You can read the input as mentioned in other answers. I just tried the main logic in this way. If combining two maps can be done, you can try this way.
String input = "Laxman";
HashMap<String, String> street = new HashMap<String, String>();
street.put("1", "Sachin Tendulkar");
street.put("2", "Dravid");
street.put("3", "Sehwag");
street.put("4", "Laxman");
for (Map.Entry<String, String> entry : street.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
if (input.equals(entry.getKey())) {
System.out.println(entry.getValue());
break;
} else if (input.equals(entry.getValue())) {
System.out.println(entry.getKey());
break;
}
}
I believe you'll need to use Integer.parseInt to figure out whether the input is and integer or not.
Unfortunately, there isn't really a "tryParse" or something like that in java, so you'll have to just catch the exception. You could use a regex to check whether it is numeric or not, but this might be more hassle than it is worth.
As far as reading in from the console, I would use:
Scanner console = new Scanner( System.in );
Read the input as a string; if it can be parsed as an Integer, use streetno, otherwise use streetname.
You can use the Scanner class to retrieve user input. It has several useful methods like nextInt() or nextLine() which can be used to your advantage to determine if a user has entered an int or a string.
You can also make the user "say" what they are entering beforehand - int or string. But this is not very user friendly.
To get a value from a HashMap use the get(key) method, when providing the key.