So right now, I am making a simple java banking program. It allows you to add a customer and deposit/withdraw funds. Right now, I have 3 classes: Main, Bank, and Customer. Right now I have it so that when you add a customer, it asks you for a name. But right now I am having trouble naming them. I want
Customer to have a username as the object name. For example, if I typed in Bob1789 as the username, the program would do:
Customer Bob1789 = new Customer("Bob1789");
If I typed in randomcustomer123 the program would do:
Customer randomcustomer123 = new Customer("randomcustomer123");
So basically, whatever I type in the box from the scanner, to be passed to the Customer name.
Customer (whatever was typed in the scanner) = new Customer((whatever was typed in the scanner));
I have tried to do this, but java always assumes that the scanner.NextLine() is the Object name.
Is there any way to do this?
You can use a HashMap<String, Customer> for this. This allows you to store name-customer pairs.
HashMap<String, Customer> allCustomers = new HashMap<>();
To create a new customer and put it into the map,
String customerName = scanner.nextLine();
allCustomers.put(customerName, new Customer(customerName));
To get a customer with a specific name, use this:
allCustomers.get("some name");
Don't know why you want to use obj name. Probably you need to use HashMap<String, Customer> where name is the key and value is the object.
Map<String, Customer> map = new HashMap<>();
to add map.put("yourName", obj);
to fetch map.pget("yourName");
Related
I wonder how to make a registry/database list in Java. I mean if I, for example, have a variable called "data", and then I add a new entry to that called "name" with the value "David". Then I would call something like "data.name" to get the value "David".
As seen on this picture
I've been Googling but not finding anything about it.
It sounds like you want a Map from String to String. You can use a HashMap<String,String> for that.
// Create Map using HashMap
Map<String, String> data = new HashMap<String, String>();
// Set name
data.put("name", "David");
// Get name
String name = data.get("name");
System.out.println(name);
I have a bunch of objects stored in hashMap<Long,Person> i need to find the person object with a specific attribute without knowing its ID.
for example the person class:
public person{
long id;
String firstName;
String lastName;
String userName;
String password;
String address;
..
(around 7-10 attributes in total)
}
lets say i want to find the object with username = "mike". Is there any method to find it without actually iterating on the whole hash map like this :
for (Map.Entry<Long,Person> entry : map.entrySet()) {
if(entry.getValue().getUserName().equalsIgnoreCase("mike"));
the answers i found here was pretty old.
If you want speed and are always looking for one specific attribute, your best bet is to create another 'cache' hash-map keyed with that attribute.
The memory taken up will be insignificant for less than a million entries and the hash-map lookup will be much much faster than any other solution.
Alternatively you could put all search attributes into a single map (ie. names, and ids). Prefix the keys with something unique if you're concerned with collisions. Something like:
String ID_PREFIX = "^!^ID^!^";
String USERNAME_PREFIX = "^!^USERNAME^!^";
String FIRSTNAME_PREFIX = "^!^FIRSTNAME^!^";
Map<String,Person> personMap = new HashMap<String,Person>();
//add a person
void addPersonToMap(Person person)
{
personMap.put(ID_PREFIX+person.id, person);
personMap.put(USERNAME_PREFIX+person.username, person);
personMap.put(FIRSTNAME_PREFIX+person.firstname, person);
}
//search person
Person findPersonByID(long id)
{
return personMap.get(ID_PREFIX+id);
}
Person findPersonByUsername(String username)
{
return personMap.get(USERNAME_PREFIX+username);
}
//or a more generic version:
//Person foundPerson = findPersonByAttribute(FIRSTNAME_PREFIX, "mike");
Person findPersonByAttribute(String attr, String attr_value)
{
return personMap.get(attr+attr_value);
}
The above assumes that each attribute is unique amongst all the Persons. This might be true for ID and username, but the question specifies firstname=mike which is unlikely to be unique.
In that case you want to abstract with a list, so it would be more like this:
Map<String,List<Person>> personMap = new HashMap<String,List<Person>>();
//add a person
void addPersonToMap(Person person)
{
insertPersonIntoMap(ID_PREFIX+person.id, person);
insertPersonIntoMap(USERNAME_PREFIX+person.username, person);
insertPersonIntoMap(FIRSTNAME_PREFIX+person.firstname, person);
}
//note that List contains no duplicates, so can be called multiple times for the same person.
void insertPersonIntoMap(String key, Person person)
{
List<Person> personsList = personMap.get(key);
if(personsList==null)
personsList = new ArrayList<Person>();
personsList.add(person);
personMap.put(key,personsList);
}
//we know id is unique, so we can just get the only person in the list
Person findPersonByID(long id)
{
List<Person> personList = personMap.get(ID_PREFIX+id);
if(personList!=null)
return personList.get(0);
return null;
}
//get list of persons with firstname
List<Person> findPersonsByFirstName(String firstname)
{
return personMap.get(FIRSTNAME_PREFIX+firstname);
}
At that point you're really getting into a grab-bag design but still very efficient if you're not expecting millions of entries.
The best performance-wise method I can think of is to have another HashMap, with the key being the attribute you want to search for, and the value being a list of objects.
For your example this would be HashMap<String, List<Person>>, with the key being the username. The downside is that you have to maintain two maps.
Note: I've used a List<Person> as the value because we cannot guarantee that username is unique among all users. The same applies for any other field.
For example, to add a Person to this new map you could do:
Map<String, List<Person>> peopleByUsername = new HashMap<>();
// ...
Person p = ...;
peopleByUsername.computeIfAbsent(
p.getUsername(),
k -> new ArrayList<>())
.add(p);
Then, to return all people whose username is i.e. joesmith:
List<Person> matching = peopleByUsername.get("joesmith");
Getting one or a few entries from a volatile map
If the map you're operating on can change often and you only want to get a few entries then iterating over the map's entries is ok since you'd need space and time to build other structures or sort the data as well.
Getting many entries from a volatile map
If you need to get many entries from that map you might get better performance by either sorting the entries first (e.g. build a list and sort that) and then using binary search. Alternatively you could build an intermediate map that uses the attribute(s) you need to search for as its key.
Note, however, that both approaches at least need time so this only yields better performance when you're looking for many entries.
Getting entries multiple times from a "persistent" map
If your map and its valuies doesn't change (or not that often) you could maintain a map attribute -> person. This would mean some effort for the initial setup and updating the additional map (unless your data doesn't change) as well as some memory overhead but speeds up lookups tremendously later on. This is a worthwhile approach when you'd do very little "writes" compared to how often you do lookups and if you can spare the memory overhead (depends on how big those maps would be and how much memory you have to spare).
Consider one hashmap per alternate key.
This will have "high" setup cost,
but will result in quick retrieval by alternate key.
Setup the hashmap using the Long key value.
Run through the hashmap Person objects and create a second hashmap (HashMap<String, Person>) for which username is the key.
Perhaps, fill both hashmaps at the same time.
In your case,
you will end up with something like HashMap<Long, Person> idKeyedMap and HashMap<String, Person> usernameKeyedMap.
You can also put all the key values in the same map,
if you define the map as Map<Object, Person>.
Then,
when you add the
(id, person) pair,
you need to also add the (username, person) pair.
Caveat, this is not a great technique.
What is the best way to solve the problem?
There are many ways to tackle this as you can see in the answers and comments.
How is the Map is being used (and perhaps how it is created). If the Map is built from a select statement with the long id value from a column from a table we might think we should use HashMap<Long, Person>.
Another way to look at the problem is to consider usernames should also be unique (i.e. no two persons should ever share the same username). So instead create the map as a HashMap<String, Person>. With username as the key and the Person object as the value.
Using the latter:
Map<String, Person> users = new HashMap<>();
users = retrieveUsersFromDatabase(); // perform db select and build map
String username = "mike";
users.get(username).
This will be the fastest way to retrieve the object you want to find in a Map containing Person objects as its values.
You can simply convert Hashmap to List using:
List list = new ArrayList(map.values());
Now, you can iterate through the list object easily. This way you can search Hashmap values on any property of Person class not just limiting to firstname.
Only downside is you will end up creating a list object. But using stream api you can further improve code to convert Hashmap to list and iterate in single operation saving space and improved performance with parallel streams.
Sorting and finding of value object can be done by designing and using an appropriate Comparator class.
Comparator Class : Designing a Comparator with respect to a specific attribute can be done as follows:
class UserComparator implements Comparator<Person>{
#Override
public int compare(Person p1, Person p2) {
return p1.userName.compareTo(p2.userName);
}
}
Usage : Comparator designed above can be used as follows:
HashMap<Long, Person> personMap = new HashMap<Long, Person>();
.
.
.
ArrayList<Person> pAL = new ArrayList<Person>(personMap.values()); //create list of values
Collections.sort(pAL,new UserComparator()); // sort the list using comparator
Person p = new Person(); // create a dummy object
p.userName="mike"; // Only set the username
int i= Collections.binarySearch(pAL,p,new UserComparator()); // search the list using comparator
if(i>=0){
Person p1 = pAL.get(Collections.binarySearch(pAL,p,new UserComparator())); //Obtain object if username is present
}else{
System.out.println("Insertion point: "+ i); // Returns a negative value if username is not present
}
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 am using a class where I am taking input as the file name and the file location. I have a pre defined file names, so I will match the predefined file names with the file name that I received and then store the values accordingly. Please look at the code below
//Set of storage maps and tables
public class storage
{
//Storage set
public static Set<Integer> tiger = new HashSet<Integer>();
//Storage set
public static Set<Integer> lion = new HashSet<Integer>();
//This is the table used for storing the browser customer count
public static Table<String,String,Integer> elephant = HashBasedTable.create();
//Storage map
public static Map<String, String> monkey = new HashMap<String, String>();
public static void storeDataDirector(String fileLocation,String fileName) throws Exception
{
if (fileName = monkey)
**update the "monkey map"**
}
This is my problem, also I have lot of maps and tables to be used so I wouldn't be able to use multiple if conditions and then check and update the same.
What I would like to know is the below
As I have said earlier, The file name that I am sending to the program which is "String filename" has the same name of the "Map monkey" but the former is a String and the latter is the map. I would like to know if I will be able to use the string variable as a reference to the map instance as both of them have the same name . This will highly avoid the if conditions that I am using in the program and thus I would like to possible solution for this ... Anything related to type caseting ort
You need to have another Map - whose key is a String and value is a Map. Something like Map<String,Map> allMaps = new HashMap<String,Map>()
Once you have this map , populate it with all your filenames and the corresponding maps monkey.
allMaps .put("monkey", monkey)
If a string filename corresponds to not a map but to a set , then you need to declare something more general Map<String,Object> allMaps = new HashMap<String,Object>(). Ofcourse this means you need to cast the value to its particular type before you can do any meaningful thing with it.
Then , to use this map , use your filename argument
Map monkeyAgain = allMaps.get(filename)
You can use reflection:
Storage.class.getField(fileName).get(null)
You will still have to cast the returned object. I do not think this the right approach.
The idea is to relate them in a Map, and use the file name as a key for example
Map<String, Map<String, String>>
// file store structure
If you need a generic solution, you could solve this by implementing an abstraction of your store structure, by implementing an interface similar to this one:
// T is the store type and U is the original type (String from file for instance...)
public interface StoreUnit<T, U> {
void update(U record);
List<T> list();
}
so you will have an implementation for each case (Set, Map, Table ...) and will relate it in a map using the file name as key.
monkeyFileName => MapStoreUnit<Entry<String,String>,String>
tigerFileName => SetStoreUnit<Integer, String>
elephantFileName => TableStoreUnit<Entry<Entry<String,String>,String>,String> // not sure if for Table there is something better than Entry ;)
When you wanna update some store you perform a get over the map using the file name as key, and invoking update method implemented with the record (that could be an String, complex Object) and so on. When you need to read something from there you could use the list method.