Java HashMap add key +1 to every new Value? - java

I´m writing a programm in Java. This programm should handle with a lot of diffrent values. I decided to use a HashMap, as you can see here :
public static Map<String, Map<Integer, String>> users = new HashMap<>();
So, as you see I´ve got a map with 2 keys. The first key decides about my "second HashMap". I hope you understood that, because now here is my problem.
public class test {
public static Map<Plot, Map<Integer, Player>> users = new HashMap<>();
public void test(String first, String second) {
if(users.get(first).isEmpty() {
users.computeIfAbsent(first, (a)->new HashMap<>()).put(0, null);
}
if(!users.get(first).containsValue(second)) {
users.computeIfAbsent(first, (a)->new HashMap<>()).put(/*my problem*/, second);
}
}
}
So, in the last if-statement is a comment. I don´t know what i should write in there ? This method is called by another class, but that doesnt matter. My goal is, that to every String (first Key) will be saved a certain Integer (second key) with a certain value(second String in my method).
Of course I want every String to start with 0 and have its own chronologically order. But remember, you can´t use at the start of the class a normal Integer-var, because if you should use it for every key it wouldn´t solve my problem.

If I understand you correctly, the 'inner map' (the one with type Map<Integer, String>) will at all times adhere to the following rule:
The map's keys will always cover a closed range from 0 to its size. For example, an inner map of size 8 will have as keys: `[0, 1, 2, 3, 4, 5, 6, 7].
Assuming I parsed your question correctly, you.... made a list. A list IS semantically speaking exactly that: A thing that 'maps' a closed range of integers starting from 0 to values. To read from this 'map' the value associated with 'key' 5, you just call list.get(5). To 'add' an item at the end, you just call list.add(x) instead of map.put(???, x).
Thus, the answer is as trivial as: Replace Map<Integer, String> with List<String>, replace the (a)->new HashMap<>() with a->new ArrayList<>(), and replace .put(/*my problem*/, with .add(.
If you must do this with maps, you cannot do it with hashmaps, unless you try to use map.size() as a fragile standin, which I strongly advise you don't do (as that would imply your map only works in cases where list would be better, thus proving that the map solution is inferior) – hashmaps do not have an order and thus no idea of 'what is the last / highest key'. You can use a TreeMap instead, which DOES have such concepts. You can ask it about the highest key, and then use 1 higher than that.
But I'm pretty sure you just want a list here.

Related

How to search if the value of a pair in in a stack object?

I have a stack of Pair<String key, String value>, and I would like to see if my stack contains a specific value, for example,
private Stack<Pair<String key, String value>> store = new Stack<>();
store.push("cookie", "milk");
store.push("cookie", "white");
store.push("cookie", "triple");
store.push("pie", "apple");
I want to check, given my stack, if it contains "white", without popping everything off. If it contains white, then my methods are different to if it doesn't; there is a precedence in values. Like, if it contains white do x else do y.
I know that there is a method in the Stack class search(Object O), which returns the position in the stack if it does contain it, or a -1 if it doesn't, however, I am not sure how I would do this with a Pair. Would I have to do store.search("cookie", "white"), or can it be just the "white" value?
Hi man i tried your example out and found out that there is no default implementation of Pairs in java so i searched and found this class which seems to do the job: https://stackoverflow.com/a/8446411/10721542
i then tested your example with the following code:
private static Stack<Pair<String, String>> store = new Stack<>();
public static void main(String[] args){
store.push(Pair.createPair("cookie", "milk"));
store.push(Pair.createPair("cookie", "white"));
store.push(Pair.createPair("cookie", "triple"));
store.push(Pair.createPair("pie", "apple"));
store.search(Pair.createPair("cookie", "white"));
}
The only important thing that i found out is that your Pair implementation needs to have an equals implementation or else the search function will not work.
It seems you're creating an pair object, then inserting it into a hash. I would try
store.search("white");
However, to search the stack, which contains objects, you might needs to construct a pair object containing "cookie" and "white" to search for object containing the values and not the actual values themselves.
I must ask, is there a reason you're using a stack to store key-pair values instead of a map or table?

Is it possible to group by and find top N in exactly one iteration

It defers from this How to apply to sort and limiting after groupBy using Java streams because I want to solve this problem in exactly one iteration. Imagine I have the following entity:
#Getter
#Setter
#AllArgsConstructor
public static class Hospital {
private AREA area;
private int patients;
}
public enum AREA {
AREA1, AREA2, AREA3
}
Now given a list of hospitals I want to find areas with most patients in them, here's what I have done so far:
public static void main(String[] args) {
List<Hospital> list = Arrays.asList(
new Hospital(AREA.AREA1, 20),
new Hospital(AREA.AREA2, 10),
new Hospital(AREA.AREA1, 10),
new Hospital(AREA.AREA3, 40),
new Hospital(AREA.AREA2, 10));
Map<AREA, Integer> map = findTopTen(list);
for (AREA area : map.keySet())
System.out.println(area);
}
public static Map<AREA, Integer> findTopTen(Iterable<Hospital> iterable) {
Map<AREA, Integer> iterationOneResult = StreamSupport.stream(iterable.spliterator(), false)
.collect(Collectors.groupingBy(Hospital::getArea,
Collectors.summingInt(Hospital::getPatients)));
return iterationOneResult.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(10)
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue, (o, o2) -> o,
LinkedHashMap::new));
}
Clearly I've Iterated two times in order to find the top ten areas with most patients in them( once for grouping hospital by area and calculate summation for that group and once more for finding the top ten areas).
Now what I want to know is:
Is there any better approach to solve this problem in one stream and therefore one iteration?
Is there any performance benefit for doing it in one iteration, what is the best practice for solving this kind of problem? (In my point of view on one hand when I call collect which is a terminal operation first time it iterates my iterable and saves the intermediate result in another object, in my code I named that object iterationOneResult, so using one stream and calling collect one time will omit that intermediate result which is the main benefit of using the stream in java, on the other hand, solving this problem in one iteration make it much faster).
Let me try to answer your questions, and provide some context on why they're maybe not the right ones:
Is there any better approach to solve this problem in one stream and therefore one iteration?
The fundamental issue here is that your goal is to find the groups with the maximum values, starting with just the raw members of those groups, unsorted. Therefore, before you can find maximum anything, you will need to assign the members to groups. The problem is, which members are in a group determines that group's value - this leads to the logical conclusion that you can't make decisions like "what are the top ten groups" before sorting all your members into groups.
This is one of the reasons that groupingBy is a Collector - a collector performs a terminal operation, which is a fancy way of saying it consumes the whole stream and returns not a stream but a resolved something - it "ends" the stream.
The reason it needs to end the stream (i.e. to wait for the last element before returning its groups) is because it cannot give you group A before seeing the last element, because the last element may belong to group A. Grouping is an operation which, on an unsorted dataset, cannot be pipelined.
This means that, no matter what you do, there is a hard logical requirement that you will first have to group your items somehow, then find the maximum. This first, then order implies two iterations: one over the items, a second over the groups.
Is there any performance benefit for doing it in one iteration, what is the best practice for solving this kind of problem? (In my point of view on one hand when I call collect which is a terminal operation first time it iterates my iterable and saves the intermediate result in another object, in my code I named that object iterationOneResult, so using one stream and calling collect one time will omit that intermediate result which is the main benefit of using the stream in java, on the other hand, solving this problem in one iteration make it much faster).
Re-read the above: "two iterations: one over the items, a second over the groups". These will always have to happen. However, note that these are two iterations over two different things. Given that you probably have fewer groups than members, the latter iteration will be shorter. Your runtime will not be O(2n) = O(n), but rather O(f(n, m)), where f(n,m) will be "the cost of sorting the n members into m groups, plus the cost of finding the maximal k groups".
Is there any performance benefit for doing it in one iteration
Well... no, since as discussed you can't.
What is the best practice for solving this kind of problem?
I cannot emphasize this enough: clean code.
99.9% of the time, you will waste more time optimizing with custom classes than they gain you back in performance, if they can gain you anything at all. The easy gain to be had here is minimizing the number of lines of code, and maximizing how understandable they are to future programmers.

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

about java recursion to create combination of string

The question was asking me to return set containing all the possible combination of strings made up of "cc" and "ddd" for given length n.
so for example if the length given was 5 then set would include "ccddd" and "dddcc".
and length 6 would return set containing "cccccc","dddddd"
and length 7 would return set contating "ccdddcc","dddcccc","ccccddd"
and length 12 will return 12 different combination and so on
However, set returned is empty.
Can you please help?
"Please understand extremeply poor coding style"
public static Set<String> set = new HashSet<String>();
public static Set<String> generateset(int n) {
String s = strings(n,n,"");
return set; // change this
}
public static String strings(int n,int size, String s){
if(n == 3){
s = s + ("cc");
return "";}
if(n == 2){
s = s + ("ddd");
return "";}
if(s.length() == size)
set.add(s);
return strings(n-3,size,s) + strings(n-2,size,s);
}
I think you'll need to rethink your approach. This is not an easy problem, so if you're extremely new to Java (and not extremely familiar with other programming languages), you may want to try some easier problems involving sets, lists, or other collections, before you tackle something like this.
Assuming you want to try it anyway: recursive problems like this require very clear thinking about how you want to accomplish the task. I think you have a general idea, but it needs to be much clearer. Here's how I would approach the problem:
(1) You want a method that returns a list (or set) of strings of length N. Your recursive method returns a single String, and as far as I can tell, you don't have a clear definition of what the resulting string is. (Clear definitions are very important in programming, but probably even more so when solving a complex recursive problem.)
(2) The strings will either begin with "cc" or "ddd". Thus, to form your resulting list, you need to:
(2a) Find all strings of length N-2. This is where you need a recursive call to get all strings of that length. Go through all strings in that list, and add "cc" to the front of each string.
(2b) Similarly, find all strings of length N-3 with a recursive call; go through all the strings in that list, and add "ddd" to the front.
(2c) The resulting list will be all the strings from steps (2a) and (2b).
(3) You need base cases. If N is 0 or 1, the resulting list will be empty. If N==2, it will have just one string, "cc"; if N==3, it will have just one string, "ddd".
You can use a Set instead of a list if you want, since the order won't matter.
Note that it's a bad idea to use a global list or set to hold the results. When a method is calling itself recursively, and every invocation of the method touches the same list or set, you will go insane trying to get everything to work. It's much easier if you let each recursive invocation hold its own local list with the results. Edit: This needs to be clarified. Using a global (i.e. instance field that is shared by all recursive invocations) collection to hold the final results is OK. But the approach I've outlined above involves a lot of intermediate results--i.e. if you want to find all strings whose length is 8, you will also be finding strings whose length is 6, 5, 4, ...; using a global to hold all of those would be painful.
The answer to why set is returned empty is simply follow the logic. Say you execute generateset(5); which will execute strings(5,5,"");:
First iteration strings(5,5,""); : (s.length() == size) is false hence nothing added to set
Second iteration strings(2,5,""); : (n == 2) is true, hence nothing added to set
Third iteration strings(3,5,""); : (n == 3) is true, hence nothing added
to set
So set remains un changed.

Data Structure for Storing Multi-key and Value Pairs in Java

Good evening,
I am searching for an elegant solution to implement a transition table (Specifically, for a universal pushdown automaton) that uses several discrete values for a given transition. They say a picture is worth a thousand words so here is part of my table:
State InputSymbol StackSymbol Move(NewState, Action)
------------------------------------------------------------
0 a Z0 (0, push)
0 a a (0, push)
0 a b (0, pop)
0 b Z0 (1, push)
...
Now, I have considered multi-dimensional arrays, ArrayLists of ArrayLists, and other solutions of the sort but all seem rather brutish. This is further complicated by the fact that every possible combination of my three symbols (a, b, and Z0) is not represented in the table.
I have been contemplating using a HashMap, but I am not entirely sure how to make this work with multiple key values. I was considering concatenating all three symbols together and using the resultant string as my key but that, too, seems less than elegant.
And, for the record, this is homework but actually giving an elegant solution is not strictly required. I just enjoy good code.
Thank you in advance for your assistance.
Make a class like this:
class Key{
int state;
char inputSysmbol;
String StackSymbol;
}
Then use the map Map<Key,Move>.
Make a class for Move just like above and don't forget to override hashcode and equals method in both classes.
Encapsulate {State, InputSymbol, StackSymbol} in an object. Then, use the "hashcode()" of the object as the key for your hash table. For more information regarding hash codes see Doc.
Take a look on MultiHashMap from Jakarta commons collections framework.
http://commons.apache.org/collections/api-release/org/apache/commons/collections/MultiHashMap.html
Unfortunately jakarta collection framework is not parametrized, i.e. does not support generics, so you will have to cast you your specific type.
Other solution is to implement something similar your self. Create class Move that holds your data. Create class Table that encapsulate the logic. This class may contain a list (better LinkedList) of Moves and N maps:
Map> stateIndex
Map> inputSymbolIndex
etc, etc.
implementation of add method is trivial.
Implementation of get is more interesting:
public Move get(Integer state, Character inputSymbol, StackSymbol stackSymbol) {
List<Move> stateList = stateIndex.get(state);
List<Move> inputSymbolList = stateIndex.get(inputSymbol);
List<Move> stackSymbolList = stateIndex.get(stackSymbol);
Set<Move> result = new HashSet<Move>(stateList);
result.retainAll(inputSymbolList);
result.retainAll(stackSymbolList);
if (result.size() > 1) {
throw new IllegalStateException("Unique constraint violation");
}
return result.size() == 0 ? null : result.interator().next();
}

Categories