I have been given an exercise to develop an appropriate data structure to implement a tennis court booking system.
A hashmap is what is required for this and I was given a diagram as a visual representation of the data structure.
From looking at the diagram, I am unclear on how the Key and Value should be defined in the HashMap. Should 'Court' be a class, which is the Key?
For the value, it shows a time, and a players name. How would the value be defined, since it has two values of time and player name?
diagram link
Say we have a HashMap named as "Date1".
Well, now i can put a value with a key in this "Date1" HashMap & later can retrieve that value with the key -> Date1.get("key")
According to your diagram, the keys will be court1, court2, ....
So that, when i will ask for Date1.get("court1"), i can get this ArrayList
But, in this arraylist, each row consist of two values. If our list had one string values in each row, we could say that this is a arraylist of string type.
So lets make our own class (like a type) which can store two values (like "9:00", "player")
public class EntryInfo{
String time, player;
public EntryInfo(String time, String player) {
this.time = time;
this.player = player;
}
}
So if we create an object of "EntryInfo" class, that object will be able to store two values - and each row of our arraylist is of this type.
so, lets sum up :
our hashmap key will be "court1, court2..."
and each key will hold values of ArrayList<EntryInfo> type.
So our hashmap will be like HashMap< String, ArrayList<EntryInfo> >
Now, lets imagine the scenario according to your diagram.
first, lets talk about usage scenario.
Say, there are several courts in your school. They are named as court1, court2, court3, ...
well, I want today's entry-log for court1.
So, i will just ask for feb9.get("court1"), and it will return a list (ArrayList), and i can traverse that array to see the log like following:
for(EntryInfo entryinfo : feb9.get("court1") ) {
System.out.println(entryinfo.time + " : " + entryinfo.player);
}
Yeah, thats it. If i want to get the log for court2, i will retrieve the value using key "court2"
Now, lets discuss how to make this.
well today is feb9, lets make a hashmap to store today's entry log. Lets name the hashmap "feb9"
HashMap<String, ArrayList<EntryInfo>> feb9 = new HashMap<String, ArrayList<EntryInfo>>();
your school has 3 courts. Lets add 3 different keys to this hashmap so that it can hold 3 separate and corresponding entry-logs for each key(court)
feb9.put("court1", new ArrayList<EntryInfo>());
feb9.put("court2", new ArrayList<EntryInfo>());
feb9.put("court3", new ArrayList<EntryInfo>());
You can relate this with creating 3 new files named court1, court2 & court3. Each file consists of an ArrayList object, which is empty for now.
Say, now at 9:00 am, player "zineryt" enters court1. Lets entry the log into our hashmap
feb9.get("court1").add(new EntryInfo("9:00", "zineryt"));
Here feb9.get("court1") will return an ArrayList, and we used add() method to insert elements into the ArrayList.
say, at 9:50am, player "bigboy" enters court1. We can entry the log like below
feb9.get("court1").add(new EntryInfo("9:50", "bigboy"));
and it goes like this.
For tomorrow's information, we will create another new HashMap named feb10 and will follow the same steps.
Date1 (what a name) is a Map<String, Court> of courts by name, like "court1". Court has fields name and a reservation list.
So the key is (probably) a String, and the class itself is the value. One often sees, that the key/ID is also kept in the value class. So a Court object suffices to get its name.
Creating a HashMap for each Date1 is an odd and confusing approach for a HashMap can't really represent a date as we understand it. but given that this is the assignment, you have to keep information about the court number, the playtime and the competitors names. These are at least three fields, if we concat the competitors names to one String.
With only using HashMap you will probably have to use a multi-dimensional HashMap.
HashMap<Integer, HashMap<String, String>> Date1 = new HashMap<String, HashMap<String, String>>();
The outer HashMap holds the court number as the key of type Integer and the pairings as the value of type HashMap.
The inner HashMap holds the playtime as key of type String (though you might as well use the type Time) and the competitors names as value of type String.
When creating this, it is vital to generate addintional accessors to avoid tedious chained calls of Date1.get(someIntVariable).get(someStringOrTime) to receive the players names.
public HashMap<String, String> getPairingsForCourt(int court) {
return Date1.get(court);
}
public String getPlayersForCourtOnTime(int court, String time) {
return getPairingsForCourt(court).get(time);
}
By any chance getting familiar with all the aspects of HashMap requires some time. Especially if you come across mechanisms like keySet() or entrySet(). Have a look on here for a detailed yet understandable start:
A Guide to Java HashMap
Related
I am doing a University assignment about developing a Dataframe library (we are supposed to import the data from files such as csv, json and txt). The data structure I chose is HashMap<String, ArrayList<Object>> where the key represents a column label and the value (List) is the column values storage. When the program reads a file the first row goes through a filter which determines which kind of Object it is (Integer, String...) in order to add the data in that way (list.add(new Integer(2)) for example) but I'm not sure if it is the best way to proceed because the program is supposed to make some operations as well such as sort values (comparator), query (predicate)... Take into account every column can contain a different data type.
I also thought about using ArrayList<String> instead and transforming the values when necessary but would not be too optimal and I prefer asking you first.
Thanks a lot in advance.
Example:
LatD LatM LatS NS LonD LonM LonS EW City State
41 5 59 N 80 39 0 W Youngstown OH
Assignment document: https://drive.google.com/file/d/1Saqiw23vQk7Yoh2csmuH2adcktNzDmjP/view?usp=sharing
I'd try using Guava's Multimap instead of constructing Map with List values yourself.
On the other hand I would think about the design. Is the number of columns always the same and you know upfront what values are there? If the answer is yes, how about creating your custom value object with named fields of concrete types? Something like this sample below and implement some Comparators etc if required.
public class ValueRow {
private Integer LatD;
...
private String City;
private String State;
...
}
So I have a list of objects, say a list of Students with variables like username, roll number, standard, division, etc.
I am looking out for a data structure that can store student objects and also allows search on any of the above variables. The time complexity is the key part here as there will be thousands of the searches done on the data.
Ex: If I use Binary Tree, then I can take a hashcode of the any variable say, username and then take an index out of it and store the student object in the Binary Tree. However, this has a limitation, as say if I want to search the student on the standard then it is not possible as the index at which the Student is stored in the Binary Tree was generated from username.
Is there any data structure, that can allow storing student once and also allows searching student on the different variables. OR Any hybrid data structure that can be created to fulfill the requirement.
I'd like to achieve a time complexity of O(1) at best else O(log n).
If you want to find all students that have a particular roll number or particular standard, then you could maintain a many hashmaps to students:
HashMap<Standard, List[Student]>
HashMap<RollNumber, List[Student]>
HashMap<Username, Student> (assuming usernames are unique)
For some fields (e.g. roll number, standard) that are just integers, you could use an array instead of a HashMap.
However, if you want to find to support queries like "find all students in a standard 5 whose roll numbers are between 5 and 10", then you'd have to do a lookup in two hashmaps and intersect the values.
If you want these operations to be quick, k-d trees might help.
If I were to do this, I would create an array of Students, where the index of each Student would be its ID.
Then, I would create a HashMap<String, Integer> to map the username to an ID, another HashMap<Integer, Integer> to map roll number to an ID, etc.
Considering username, roll numbers are unique for every student and standard, divisions can be shared by multiple students.
You can work out a solution in fallowing manner to achieve the O(1)/O(log(N))/O(N) depending upon the cases.
Lets define the class structure first :
class Student{
// Considering all the variables to be string. You can change them according to your use cases.
String username;
String rollNumber;
String standard;
String division;
}
Lets create some maps to store these students
Map<String, Student> usernameMap; // username to object map
Map<String, Student> rollNumberMap; // roll number to object map
Whenever any Student objectis created you add those respective Maps.
Incase you want to find out all the Students in any given standard/division,
you can keep the another mapping for standards and divisions also.
Something like ->
Map<String, Set<String>> standardMap; // standard to set of student's username/rollnumber.
you can create similarly map for divisions.
So I have the arrayList called inPeople, which has this class stored in it named peopleIn. This is the data stored in the class
peopleIn( int scannerNum, Date date, int empNum){
So basically, my program is a system which reads through the logs of a punch clock to find out who's in the building. The problem is, if the person punches in a number of times, but never punches out, i end up with duplicates in my list. So basically, I need to keep the most recent punch in.
Can this be done?
You can use Map<Key,Value>, If you put value for same key. previous value will be replace by current value.
Eg:
Map<String,String> map=new HashMap<>();
map.put("emp1", "val1");
map.put("emp2","val2");
System.out.println(map);
// now i am putting emp1, val3
map.put("emp1","val3");
System.out.println(map);
Out put:
{emp2=val2, emp1=val1}
{emp2=val2, emp1=val3}
You can store them in a Map, where the key is the employee number and the value is the date. This will prevent the duplicates.
Are there any potential issues that could arise from using a Key on different maps as follows.
Map<Key, Value> employeeBasicInfo= new HashMap<>();
Map<Key, Value> employeeDetailInfo = new HashMap<>();
....
//EDIT: Lets assume this is a unique key where every department has unique employee names.
String firstName = "John";
String lastName = "Smith";
String department = "IT";
Key employeeKey = new Key(firstName, lastName, department );
Value employeeBasicInfo = new Value(salary,grade,dateHired....);
Value employeeDetail = new Value(performanceEvaluation,benefit,familyInfo,...);
employeeBasicInfo.put(employeeKey, employeeBasicInfo);
employeeDetailInfo.put(employeeKey, employeeDetail);
NOTE:The key is used twice with employeeBasicInfo and employeeDetailInfo
Assuming the key above will be unique(no two people will have the name John Smith in the same department), is this considered as a bad programming practice, if so what are the reasons?
Thank you!
It's okay to have one key point to two pieces of data, but the data structure for it feels wrong - you have to maintain two separate maps, and if the data in one is mutated, then you've lost the key forever.
You shouldn't mutate the key, but what you can do is store them in one data structure: a Multimap. It's part of Guava's suite.
final Multimap<Key, Value> employeeInfo = ArrayListMultimap.create();
employeeInfo.put(employeeKey, employeeBasicInfo);
employeeInfo.put(employeeKey, employeeDetail);
What this gives you is equivalent (in a sense) to a Map<Key, Collection<Value>>, and since you know the order in which you put these elements in, retrieval is straightforward.
Value basicInfo = ((List<Value) employeeInfo.get(employeeKey)).get(0);
Value detail = ((List<Value>) employeeInfo.get(employeeKey)).get(1);
You have to perform the cast, since Collection has no notion of a get(int index).
It's perfectly valid to use the same Key on different maps (as long as you don't mutate the key value). Using the same value is fine too (as long as you don't mutate it). For example, I might use a "name" to index a person's address and their date of birth in two maps.
In general it is very common to have the same key in diffrent maps. There is no problem with that.
In your specific example you have name and department as key but at least the department could change. In that case the map would not work. I can't see why you even need the map in the first place.
I am trying to add to a collection the following pairs
698xxxxxxx - personA
698xxxxxxx - personB
699xxxxxxx - personA
699xxxxxxx - personB
I go through alot of files and try to add to a collection the pairs i find there. I want to be able to have a table that will show each number and what people it was correlated with without having dublicate PAIRS. for example
1-personA ok
1-personB ok
2-personA ok
3-personB ok
3-personB NOT OK as its already there
I tried using a Multimap but i m not sure if its the right choice. Whatever the solution is please show me how to iterrate through its values as well so i can use the pairs. Sorry for the demanding post but i m new with Java and i find a lil hard to understand the APIs.
Thanks in advance
There are three obvious alternative, depending on what you require.
If there can only be one person for each phone number, then a simple Map<PhoneNo, Name>.
If there a given phone number can be associated with multiple people, then either a Map<Phone,Set<Name>> or a multi-map class.
If you also want to find out the phone number or numbers for each person, you need two maps or two multi-maps ... or a bidirectional map.
There is a secondary choice you need to make: hash-table versus tree-based organizations. A hash table will give you O(1) lookup/insert/remove (assuming that the hash function is good). A tree-based implementation gives O(logN) operations ... but it also allows you to iterate over the entries (or values) in key order.
While the standard Java class libraries don't provide multi-maps or bidirectional maps, they can easily be implemented by combining the simple collection classes.
You can choose Map Interface in Java, which accepts key and value pairs.
You can have this as a reference: http://www.tutorialspoint.com/java/java_map_interface.htm
You may need a hashmap with the key as the name of the person and value as a HashSet of numbers. Hashset does not allow duplicates, so duplicate numbers will not be stored in that. Here is the code:
HashMap<String,HashSet> Records;
In Java there is a couple of options. If you don't know about the cardinality of persons or numbers, then go for:
public class Pair {
String person;
String number;
}
Then use a Set to be save from doublettes like
Set<Pair> pairs = new HashSet<>();
....
pairs.add( new Pair( "689xxxx", "personA" );
for ( Pair pair : pairs ) {
System.out.println( pair.number + " - " + pair.person );
}
Hajo