Using a key on different maps - java

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.

Related

Java - HashMap for booking system

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

Storing multiple values with same key in HashMap

I had an interview today and my interviewer asked me that how can I store multiple values having the same key in HashMap?
She gave me this example-->If I am given a list of String and I am suppose to store the length of String as key and the String itself as value.
I gave her the following solution in how I will be using HashMap:
Map<Integer, ArrayList<String>> map = new HashMap<Integer, ArrayList<String>>();
Integer being the length of the String and the ArrayList will store the Strings of that particular length.
The interviewer said that this is one way of using the HashMap but there is another way in which I won't be requiring ArrayList or any other data structure. During interview, I couldn't come up with any solution and now after enough googling, I still have nothing. Can anyone tell me how can I achieve the solution to this question?
Thanks!
One way without using ANY DATA STRUCTURE is concatenating all strings in values.
For e.g.
map.put(2,"rr*tt*yy");
map.put(3,"nnn*ggg*sss");
map.put(4,"ffff*dddd*jjjj");
May be the interviewer was looking to check if you know the 3rd party APIs or not.
There are multiple APIs available to do this.
Some of them can be found at
http://java.dzone.com/articles/hashmap-%E2%80%93-single-key-and
One option is every time you want to insert a record into the map, get the length of the String, salt then encrypt the size of the String to use as the key. BAM: you have a (fairly) unique retrievable key for each String without having to much around with String concatenation.
Just make sure you use a reversible encryption algorithm.
Another option would be to generate out a UUID and concatenate the size of the string to that.
UUID uuid = UUID.randomUUID()
String key = stringSize + "," + uuid;
This will also result in a unique value that you can retrieve later using String.split();

Which collection is suitable for tel number + name pair in Java?

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

How to get the number of occurrences of a key in HashMap?

I am have the Hashmap like this,
HashMap<String,String> epnSource = new HashMap<String, String>();
Now I have added the keys/values like this,
epnSource.put("10.3.2.227","EPN1");
epnSource.put("10.3.2.227","EPN2");
epnSource.put("10.3.2.166","EPN3");
epnSource.put("10.3.2.166","EPN4");
epnSource.put("10.3.2.161","EPN5");
I am trying to do every time before adding a value, I want to check number of occurrences of a key present in the HashMap. Suppose if key 10.3.2.227 has more than two occurrences I shouldn't added it and go for new one. Any suggestions will be helpful.
Suppose if value 10.3.2.227 has more than two occurrences ...
It won't. The way that you have implemented it, the "10.3.2.227" is a key of the Map, and a given key cannot appear more than once in a Map.
If you want a given key (e.g. "10.3.2.227") to map to multiple values (e.g. "EPN1" and "EPN1"), you need to use either a Map<String,Set<String>> or a MultiMap class from the Apache or Google/Guava collections libraries.
If the map previously contained a mapping for the key, the old value is replaced.
It is not possible duplicate key in HashMap.

What data structure could I use for counting occurrences of a country code?

I need some kind of data structure don't know yet which would be most suitable.
Here is what I'm working with: I have a bunch rows of data processing and each row has its own country code.
I want to obtain as result how many times each country code repeats throughout the process.
You might try a HashMap. With a HashMap, you can use the country code as the key, and the count of how many times each appears as the value stored in that key. If you encounter a particular country code for the first time, insert it into the map with an initial value of 1; otherwise, increment the existing value.
HashMap<String, Integer> myMap = new HashMap<String, Integer>();
for (... record : records) {
String countryCode = record.getCountryCode();
int curVal;
if (myMap.containsKey(countryCode)) {
curVal = myMap.get(countryCode);
myMap.put(countryCode, curVal + 1);
} else {
myMap.put(countryCode, 1);
}
}
// myMap now contains the count of each country code, which
// can be used for whatever purpose needed.
I would use a HashMap with the country code as the key and the count as the value. Build the map from your collection and increment the count if it is already in the map.
Create a Map using country code String as the key and the current count as the value.
You realize, of course, that you can get such a thing directly out of a SQL query:
select country_code, count(country_code)
from your_table
group by country_code
order by country_code
You'll get a ResultSet with country code and count pairs. That's easy to load into a Map.
To complete the answer with something other than HashMap.
If your country code list is or can easily be turned into a not very sparse numeric sequence, try a int[] or long[].
If your country code range is sparse, but don't have many elements, create a CountryCode enum And use a EnumMap to store the amounts:
Example:
Map<CountryCode, Long> countryCodeAppearances =
new EnumMap<CountryCode,Long>(CountryCode.class);
Lightweight data structures will perform better and impose less memory / garbage collection overhead. So, array should be the fastest. EnumMap is kind off a hidden gem that, under the right circumstances may also give you a performance boost.
Guava offers the AtomicLongMap

Categories