How implement data structure which is map many to one? - java

I want to have map in reverse direction which is mean I have lots of keys and only one value. I need this structure so when I search for one of the key I got the value.
I can use a simple Hash Map but it waste space because of storing value many times. I am looking for optimize and efficient implementation in java. I appreciate your suggestion.

HashMap should be used. when you put "cloth" into HashMap as a value, it is not duplicated in memory. just reference is written into HashMap.
String hat = "hat";
String dress = "dress";
String paths = "paths";
String scarf = "scarf";
String cloth = "cloth";
HashMap h = new HashMap();
h.put(hat,cloth);
h.put(paths,cloth);
h.put(dress,cloth);
h.put(scarf,cloth);
for this sample, memory keeps only cloth object for once.

You don't waste space because each entry shares a reference to the same object. Please post some code if you want a more elaborated answer.

Related

Map.Entry<> java

I have no idea about java whatsoever but I found this blockchain guide in java and I have been trying to understand and convert the code in C++ (my thing). I was doing good so far but I am stuck here. I cant understand this for loop and Map.Entry<> thing. Any kind of help is appreciated.
And also I am new to blockchain.
The link to this guide is:
https://medium.com/programmers-blockchain/creating-your-first-blockchain-with-java-part-2-transactions-2cdac335e0ce
If that helps.
Here is the code:
public class Wallet {
public PrivateKey privateKey;
public PublicKey publicKey;
public HashMap<String,TransactionOutput> UTXOs = new HashMap<String,TransactionOutput>();
public float getBalance() {
float total = 0;
for (Map.Entry<String, TransactionOutput> item: NoobChain.UTXOs.entrySet()){
TransactionOutput UTXO = item.getValue();
if(UTXO.isMine(publicKey)) { //if output belongs to me ( if coins belong to me )
UTXOs.put(UTXO.id,UTXO); //add it to our list of unspent transactions.
total += UTXO.value ;
}
}
return total;
}
What is this for loop doing is beyond me. If anyone could provide a simpler C++ version of this loop.
Instead of just providing a C++ code snipped let me try to explain this:
In java there are data structures called Maps which contain key-value pairs (you probably could guess this part). The Map itself is not iterable, so in order to loop through a map you can loop through all its keys (also called a key set), all the values or all the key-value pairs (also know as the Entry set). The latter happens in your example.
So in your example you have a map of String (the keys) and TransactionOutput objects (values). The for, loops through these pairs and each pair is stored in the variable item. Then the value part is extracted from the key-value pair (item) which is a TransactionOutput object.
Then this object is verified with the method isMine() and if that is true, it is added to another Map (calles UTXOs) that maps Strings (the key) to TransactionOutput object. In this case it seems the string (the key in the map) is the id of the TransactionObject.
The variable total is increased by the value of the added TrasactionOutput.
Side note: This for-loop could as well just loop through all the values in the map since the key is never used in this particular loop.
Now, to explain this in other words, it is going through the map of TransactionOutputs, the ones that belong to "me" are put aside in a separate map and the total amount of the TrasactionOutput values that belong to "me" is returned.
Hope this clears things up!
Good luck,
Teo

Best pratice for using array as the key of memoization in Java

I am doing some algorithm problems in Java, and from time to time the problem needs memoization to optimize speed. And often times, the key is an array. What I usually uses is
HashMap<ArrayList<Integer>, Integer> mem;
The main reason here to use ArrayList<Integer> instead of int[] is that the hashCode() of an primitive array is calculated based on the reference, but for ArrayList<Integer> the value of the actual array is compared, which is desired behavior.
However, it is not very efficient and code can be pretty lengthy as well. So I am wondering if there is any best practice for this kind of memoization in Java? Thanks.
UPDATE: As many have pointed this out in the comments: it is a very bad idea to use mutable objects as the key of a HashMap, which I totally agree.
And I am going to clarify the question a little bit more: when I use this type of memoization, I will NOT change the ArrayList<Integer> once it is inserted to the map. Normally the array represents some status, and I need to cache the corresponding value for that status in case it is visited again.
So please do not focus on how bad it is to use a mutable object as the key to a HashMap. Do suggest some better way to do this kind of memoization please.
UPDATE2: So at last I choose the Arrays.toString() approach since I am doing algorithm problems on TopCoder/Codeforces, and it is just dirty and fast to code.
However, I do think HashMap is the more reasonable and readable way to do this.
You can create a new class - Key, put an array with some numbers as a field and implement your own hascode() based on the contents of the array.
It will improve the readability as well:
HashMap<Key, Integer> mem;
If your ArrayList contains usually 3-4 elements,
I would not worry much about performance. Your approach is OK.
But as others pointed out, your key is thus mutable which is
a bad idea.
Another approach is to append all elements of the ArrayList
together using some separator (say #) and thus have this kind
of string for key: 123#555#66678 instead of an ArrayList of
these 3 integers. You can just call Arrays.toString(int[])
and get a decent string key out of an array of integers.
I would choose the second approach.
If the input array is large, the main problem seems to be the efficiency of lookup. On the other hand, your computation is probably much more expensive than that, so you've got same CPU cycles to spare.
Lookup time will depend both on the hashcode calculation and on the brute-force equals needed to pinpoint the key in a hash bucket. This is why the array as a key is out of the question.
The suggestion already given by user:XpressOneUp, creating a class which wraps the array and provides its custom hash code, seems like your best bet and you can optimize hashcode calculation to involve only some array elements. You'll know best which elements are the most salient.
If the values in the array are small integer than here is way to do it efficiently :-
HashMap<String,Integer> Map
public String encode(ArrayList arr) {
String key = "";
for(int i=0;i<arr.size();i++) {
key = key + arr.get(i) + ",";
}
return(key);
}
Use the encode method to convert your array to unique string use to add and lookup the values in HashMap

Which Array / List should I use to keep an static index?

I usually use HashMap<Integer, Object> to keep an array of objects where you can get items by Integer.
I'm showing you an example so you can understand.
HashMap<Integer,String>:
[0] - Hello
1 - How are you doing
[2] - Bye
So with a HashMap, I can remove items avoiding the rest moving from their indexes.
hashmap.remove(0)
[0] - null
1 - How are you doing
[2] - Bye
But HashMap shouldn't be used for indexes with an Integer. So... Which kind of array should I use to perform actions like the ones I am explaining above?
Edit: About the part of "shouldn't be used", this is what Android Eclipse is telling me:
You can use a simple Array. They can be pointed by integer. And other than calling remove you can set null to the specific place. If you really want to call remove write your own wrapper method which does that for you.
I your indices are dense (no big holes in a range [0..n], the most efficient approach would be to use a plain array of String:
final String[] lup = new String[3];
lup[0] = "Hello";
lup[1] = "How are you doing";
lup[2] = "Bye";
// to remove elements just set the index to `null`:
lup[0] = null;
You can use SparseArray which is similar to HashMap<Integer,String>
SparseArray<String> arr=new SparseArray<String>();
arr.put(0, "Hello");
If you already know the total size, then go with Arrays. But if you don't then go with ArrayList.
Now, I don't see a purpose of mapping here.
Hashmap is a Map data structure. Like a list each item that is stored in a hashmap is stored at a particular index. This index is called a hash and it is generated using a hash function. Hash functions accept the object to be stored as an argument and generate a number that is unique to it. Different hashing functions have different trade-offs. A function that is too sparse will use up more space than required(your case). while one that is not sparse enough will suffer from collisions where objects use the same hash.
Further Reading if interested: Look at Android's SparseArray implementation for inspiration.
View the source by downloading AOSP's source code here http://source.android.com/source/downloading.html.
It is highly optimized for integers!
Actually, you can use a simple array of strings.
String arr[] = new String[size];
After reading a little bit, I guess the answer is the following:
1.- I can't use plain arrays. Reason: I might not know the final size of it.
2.- Lists doesnt fit, as when you remove an item, the following items fits to the new index. I don't want index move.
So as a global answer, using HashMap is OK, however using SparseArray is recommended as it is more efficient.

which is better option?

i need to maintain a list containing two values of string type say v1,v2 for each key say k.
What is a better option
Hashmap with value containing a string containing v1 and v2 and using split() to retrive the correct value after selection.
Hashmap with value containing array of two string variables
I am creating an android app, so just concern about performance. In second case i can access directly but each value will contain another array ( i dont know but it appears like a complicated way) , while in 1st case it will use split function on every access like v.split(",")[0]
Please guide me.
Map<String,String[]> listMap= new HashMap<String, String[]>();
Map<String,String> listMap1= new HashMap<String, String>();;
for (int i = 1; i < tl.getChildCount(); i++) {
TableRow row = (TableRow) tl.getChildAt(i);
COLOR_TABLE clr = (COLOR_TABLE) row.getTag();
if (clr == COLOR_TABLE.green) {
//comp
String x1=listMap1.get( ((TextView) row.getChildAt(0)).getText());
String x2=listMap.get( ((TextView) row.getChildAt(0)).getText());
// now i have to add two string values in a list seperately
}
}
Never abuse Strings! It may be slow at times and they are not made for that purpose.
You could use a generic Pair class if you want to do it more object oriented:
public class Pair<A, B> {
public A first;
public B second;
public Pair(A first, B second) {
this.first = first;
this.second = second;
}
}
Of course you can do it better, with accessors and so.
i think split function runs with O(string size) complexity but reach element of an array is a constant
The string will be much slower than the array, and also have more complicated code. (With the caveat that it is hard to be sure about performance differences until one has actually measured it.)
But if it was me, I would use the simplest solution, and use an object. Later, if the program turns out to be too slow, and measurement shows this to be a performance bottleneck, I would consider other solutions.
Using an array or a custom class as the value would be the preferred approach from a design perspective. If you pack two strings into one separated by a character you need to make sure that the first string won't ever contain that same character, or you must use some kind of an escape mechanism to be able to include it.
If you are only worried about performance test all options and pick the best one. It's hard make predictions because the results will depend on the data you store and on how libraries have been implemented. For example, any structure that stores references to independent strings will potentially suffer a cache miss on access; if the string split or a similar method turns out to be cheaper than a cache miss it will be faster.

how to get the real value of data that has been hashed?

how to get the real value of data that has been hashed? is it possible that you can still get the real value of the data after you get the hashcode?
or is there any code that can reverse the output.
String ida = new String(txtID.getText().toString());
int idb = ida.hashCode();
codeD.setText("result: " + ida );
i already get the hashcode of the txtID(the user that has been input), but now i want to get the the real value that has been hashed without calling the ida.
Short answer: no.
The long answer:
A hash is meant to be a quick, one-way calculation to roughly identify some item. In Java, hash codes are usually used to putting something into a Map. The hash code is used to identify one Object from another when it is used as a key in the HashMap. It is not meant to store the data, only be different enough to prevent collisions. It is quite possible to have two objects that have the same hash.
As CodeChimp explained, what you are trying to do is not Hashing, but Encrypt/Decrypt.
This example will help you do it: http://www.example-code.com/java/aes_dataStream.asp
If you are like me and enjoy reinventing the wheel, this could be fun to implement: http://en.wikipedia.org/wiki/Affine_cipher

Categories