Any implementation of Map<K1, K2, V>, i.e. two keys? - java

I need a map that has two keys, e.g.
Map2<String /*ssn*/, String /*empId*/, Employee> _employees;
So that I can
_employees.put(e.ssn(), e.empId(), e)
And later
_employees.get1(someSsn);
_employees.get2(someImpId);
Or even
_employees.remove1(someImpId);
I am not sure why I want to stop at two, why not more, probably because that's the case I am I need right now :-) But the type needs to handle fixed number of keys to be type-safe -- type parameters cannot be vararg :-)
Appreciate any pointers, or advice on why this is a bad idea.

I imagine the main key would be empId, so I would build a Map with that as the key, i.e. empId ---> Employee. All other unique attributes (e.g. ssn) would be treated as secondary and will use separate Maps as a lookup table for empId (e.g. ssn ---> empId).
This implementation makes it easy to add/remove employees, since you only need to change one Map, i.e. empId ---> Employee; the other Maps can be rebuilt only when needed.

My first thought was: the easiest way to do this, I think, would be two maps.
Map< String, Map< String,Employee> > _employees;
But from what it looks like, you just want to be able to look up an employee by either SSN or ID. What's to stop you then from making two maps, or at worst a class that contains two maps?
As a clarification, are you looking for a compound key being employees are uniquely identified by the combination of their SSN and ID, but not either one by itself, or are you looking for two different ways of referencing an employee?

The Spiffy Framework appears to provide exactly what you`re looking for. From the Javadocs:
A two-dimensional hashmap, is a
HashMap that enables you to refer to
values via two keys rather than one
The relevant class is TwoDHashMap. It also provides a ThreeDHashMap.

Related

Which collection should I use to easely get certain object from it by the pair of properties?

Info about network interfaces comes from several servers and must be shown in the table. Each interface must have name and serverName, they're not unique, but pair of them is.
Problem: Information comes every second, and I need to update fields of each interface with new data. So I need to get certain (identified by name and serverName) interface from some list with minimum effort (resources). Table works only with observableList, but searching through it is the overkill. It can contain thousand of interface objects.
Should I create own realization of list, which can be flatten to observableList, or the best way will be to hold HashMap<String, NetInterface> of each server (key is interface's name) with refences from observableList?
HashMap>
use as auto increment for Integer.
The best way will be using the unique thing(name+server name) as the key of your Hash Map.
Use a Map<String, Map<String, NetInterface>, where the outer key is the name and the inner key is the server name.

Java String hashcode as Mysql ID

The scenario is something like this description.
I've the typical mysql table for the users storage, currently, the user ID is one integer set as autoincrement. Very much of the API rest interfaces works with the user alias (that's unique) to find the user, then, I'm thinking implement the user ID with the alias.hashcode() (that's one integer) to find diretly for ID every times.
Is a good idea implement Mysql ID with one java String hashcode?. Would enhance the performance?
I don't think it's a great idea. The pigeon hole principle states (from Wikipedia) if n items are put into m containers, with n > m, then at least one container must contain more than one item. Basically, your solution cannot handle collisions and collisions are very possible with hashing.
Don't use String hashCode as your ID, since it's not unique. Two different Strings may have the same hashCode. I'm assuming your ID should be unique.
Just add an index on the alias column, and query the db by alias directly. There are two problems with using alias hash code or other derivatives as an id. First, as others pointed out, hash codes are not be unique (this can be almost solved by changing the id type to string, and using a digest instead of the hash. Collisions with digests, while still possible, are extremely unlikely). Second, if the user changes his alias, the value will get out of sync with the id. If functionality of your application is such, that this situation is either impossible or unimportant, then you don't really need an id at all, and can identify users by alias directly.

4 Key Value HashMap? Array? Best Approach?

I've got loads of the following to implement.
validateParameter(field_name, field_type, field_validationMessage, visibleBoolean);
Instead of having 50-60 of these in a row, is there some form of nested hashmap/4d array I can use to build it up and loop through them?
Whats the best approach for doing something like that?
Thanks!
EDIT: Was 4 items.
What you could do is create a new Class that holds three values. (The type, the boolean, and name, or the fourth value (you didn't list it)). Then, when creating the HashMap, all you have to do is call the method to get your three values. It may seem like more work, but all you would have to do is create a simple loop to go through all of the values you need. Since I don't know exactly what it is that you're trying to do, all I can do is provide an example of what I'm trying to do. Hope it applies to your problem.
Anyways, creating the Class to hold the three(or four) values you need.
For example,
Class Fields{
String field_name;
Integer field_type;
Boolean validationMessageVisible;
Fields(String name, Integer type, Boolean mv) {
// this.field_name = name;
this.field_type = type;
this.validationMessageVisible = mv;
}
Then put them in a HashMap somewhat like this:
HashMap map = new HashMap<String, Triple>();
map.put(LOCAL STRING FOR NAME OF FIELD, new Field(new Integer(YOUR INTEGER),new Boolean(YOUR BOOLEAN)));
NOTE: This is only going to work as long as these three or four values can all be stored together. For example if you need all of the values to be stored separately for whatever reason it may be, then this won't work. Only if they can be grouped together without it affecting the function of the program, that this will work.
This was a quick brainstorm. Not sure if it will work, but think along these lines and I believe it should work out for you.
You may have to make a few edits, but this should get you in the right direction
P.S. Sorry for it being so wordy, just tried to get as many details out as possible.
The other answer is close but you don't need a key in this case.
Just define a class to contain your three fields. Create a List or array of that class. Loop over the list or array calling the method for each combination.
The approach I'd use is to create a POJO (or some POJOs) to store the values as attributes and validate attribute by attribute.
Since many times you're going to have the same validation per attribute type (e.g. dates and numbers can be validated by range, strings can be validated to ensure they´re not null or empty, etc), you could just iterate on these attributes using reflection (or even better, using annotations).
If you need to validate on the POJO level, you can still reuse these attribute-level validators via composition, while you add more specific validations are you´re going up in the abstraction level (going up means basic attributes -> pojos -> pojos that contain other pojos -> etc).
Passing several basic types as parameters of the same method is not good because the parameters themselves don't tell much and you can easily exchange two parameters of the same type by accident in the method call.

What data structure to use?

I want to store information using data structure.
For example, I have a data similar to:
Code Applicable values
001 A,B,C,D
004 C,D
005 P,Q,R,S
007 S,C
..
..
..
1000 (Code, Applicable values pair)
Straightforward solution I can think of is having HashMap with key type String and value type HashSet.
I was informed before by architect that having Set in Map is not a good idea.
Any suggestion on how to go about implementing this?
A HashMap<String, HashSet<String>> looks just fine to me for holding the type of data you've shown.
That "architect" of yours might be right about too much complexity when we're talking about how that data structure is exposed to the rest of your program. For example:
That type signature above does not make any statement about what kind of strings are used as keys, and what kind of values are in the value sets. Do they represent names? Or ISBN numbers? Or any text, or only particular enumeration values? etc.
If you use such a HashMap everywhere in your code, when adding values into the sets you will have to remember everywhere to do two steps: (1) creating an empty set only if no value is in the dictionary for some given key, and (2) adding the new value to the set of a given key. Having to think about routine stuff like that opens up the door for bugs.
Perhaps it would be better to hide your actual data structure behind a nice, simple and easy-to-use "collection" interface, perhaps similar to the following:
interface ApplicableValuesCollection
{
void Add(int code, String value);
void Remove(int code, String value);
bool Contains(int code, String value);
Iterable<String> GetValuesOfCode(int code);
…
}

How to implement n:m relation in Java?

I need to implement an n:m relation in Java.
The use case is a catalog.
a product can be in multiple categories
a category can hold multiple products
My current solution is to have a mapping class that has two hashmaps.
The key of the first hashmap is the product id and the value is a list of category ids
The key to the second hashmap is the category id and the value is a list of product ids
This is totally redundant an I need a setting class that always takes care that the data is stored/deleted in both hashmaps.
But this is the only way I found to make the following performant in O(1):
what products holds a category?
what categories is a product in?
I want to avoid full array scans or something like that in every way.
But there must be another, more elegant solution where I don't need to index the data twice.
Please en-light me. I have only plain Java, no database or SQLite or something available. I also don't really want to implement a btree structure if possible.
If you associate Categories with Products via a member collection, and vica versa, then you can accomplish the same thing:
public class Product {
private Set<Category> categories = new HashSet<Category>();
//implement hashCode and equals, potentially by id for extra performance
}
public class Category {
private Set<Product> contents = new HashSet<Product>();
//implement hashCode and equals, potentially by id for extra performance
}
The only difficult part is populating such a structure, where some intermediate maps might be needed.
But the approach of using auxiliary hashmaps/trees for indexing is not a bad one. After all, most indices placed on databases for example are auxiliary data structures: they coexist with the table of rows; the rows aren't necessarily organized in the structure of the index itself.
Using an external structure like this empowers you to keep optimizations and data separate from each other; that's not a bad thing. Especially if tomorrow you want to add O(1) look-ups for Products given a Vendor, e.g.
Edit: By the way, it looks like what you want is an implementation of a Multimap optimized to do reverse lookups in O(1) as well. I don't think Guava has something to do that, but you could implement the Multimap interface so at least you don't have to deal with maintaining the HashMaps separately. Actually it's more like a BiMap that is also a Multimap which is contradictory given their definitions. I agree with MStodd that you probably want to roll your own layer of abstraction to encapsulate the two maps.
Your solution is perfectly good. Remember that putting an object into a HashMap doesn't make a copy of the Object, it just stores a reference to it, so the cost in time and memory is quite small.
I would go with your first solution. Have a layer of abstraction around two hashmaps. If you're worried about concurrency, implement appropriate locking for CRUD.
If you're able to use an immutable data structure, Guava's ImmutableMultimap offers an inverse() method, which enables you to get a collection of keys by value.

Categories

Resources