How to find next minimum in a hash map key? - java

I have a scenario where I have a map:
BiMap <Integer, String> map;
and a list which tracks the index which are processed.
List<Integer> filled;
While processing if the filled list contains the key then I should find the next min key from the map which is already not in the filled list.
Can some one tell me is there an easy way to do this without doing many iterations?
for (int i =0 ;i <size; i++) {
if(map.contiansKey(i)) {
Integer min = list.contains(i) ? getNextMinFrom(map, filled) : null;
if min != null ?System.out.println(map.get(min)) : continue;
}
}
For Eg:
Filled - 0, 4, 5, 6
Map - (1,dfs) (4,efs) (5,sdfs)
in the 0 th iteration.. output - dfs (1 is min)
in 4th iteration ... output shoudl be 4efs (4 is the next min)
....
The issue is I can not remove entries from the list.

use a TreeSet initialized with the 'KeySet' of your map and while you add Any key to filled remove it from 'TreeSet',as a result, the first element of TreeSet is what you want

Is this what you want to achieve? Start from the front of the filled array and go until you find the first value that is in filled but not in the map?
public int get smallestUnusedValue() {
for(int i = 0; i < filled.size(); i++)
if(!map.containsKey(filled.get(i)))
return i;
}

Do you need to use a HashMap specifically? Implementations of NavigableMap, such as TreeMap, provide methods to look up keys "adjacent to" a given value, without requiring an exact map. The higherEntry method seems to do what you want.

Related

Way to overcome fail-fast iterator in HashMap

In competitive programming, I was solving a given problem - given an array nums of non-negative integers, and a target sum S, we have to find out the number of ways we can obtain target sum from sum of given numbers (where each nums[i] can be taken as nums[i] or -nums[i].
Although I came across some solutions that mainly relied on direct access tables using array (it is given that sum of numbers cannot exceed 1000), but I tried it using HashMap to reduce the space required. My code is as follows -
public int findTargetSumWays(int[] nums, int S) {
Map<Integer, Integer> dp = new HashMap();
dp.put(nums[0], 1);
dp.put(-nums[0], dp.getOrDefault(-nums[0], 0) + 1);
for (int i=1; i<nums.length; i++) {
for (Integer sum : dp.keySet()) {
dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
dp.put(sum-nums[i], dp.getOrDefault(sum-nums[i], 0) + 1);
}
}
return dp.get(S);
}
But I am getting ConcurrentModificationException on running the code. I tried finding about the issue. Although I got some conceptual understanding that in iteration, view of Collections can't be structurally modified, I am not able to figure out how to find my way around it to find a solution.
Is it that a solution using HashMap(or any dynamic data structure) is not possible? Any help is appreciated.
for (Integer sum : dp.keySet()) {
dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
// ...
}
If sum + nums[i] isn't a key that's already in the map, this results in a structural modification of the map: that is, you're adding a new key/value pair.
As described in the Javadoc:
The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException.
(If the key were already in the map, you'd just be modifying the value associated with that key, and this would be fine).
The easiest way to get around this is to take a snapshot of the keys to iterate over, by copying the elements into e.g. a list:
for (Integer sum : new ArrayList<>(dp.keySet())) {
Now, you're iterating the list, not the map's keyset, so you are free to modifying the map structurally inside that loop.
Separately from the question of the exception, your put/getOrDefault lines would be more simply written as:
// dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
// becomes
dp.merge(sum+nums[i], 1, Integer::sum);
The reason for ConcurrentModificationException is that you are modifying the keys of dp while iterating dp.keySet() in the following loop:
for (Integer sum : dp.keySet()) {
dp.put(sum+nums[i], dp.getOrDefault(sum+nums[i], 0) + 1);
dp.put(sum-nums[i], dp.getOrDefault(sum-nums[i], 0) + 1);
}

Iterate through List<Object> given from Value within a Map

I am relatively unexperienced using such Java code. For getting forward in my Selenium automation I want to iterate through a Map>.
Right now I try to get near that iteration with the following code:
static Map<String, List<WebElement>> map = new Map<String, List<WebElement>>;
for (Map.Entry<String, List<WebElement>> entry : map.entrySet()) {
for (int i = 0; i < entry.getValue().size(); i++) {
*need to find code*
}
}
My intention is to iterate through all the WebElements within the Value of one Key within map
Will "entry.getValue().size()" get the Size of the List in that case? And how may I get a certain item out of the list in such a case? Any better solutions maybe?
Best regards
You can access both the key and the value from each map entry and do whatever you need. The key in this case is a string, and its value is a List<WebElement>. Once you have the list in hand, you can access its size and iterate over it.
for (Map.Entry<String, List<WebElement>> entry : map.entrySet()) {
String key = entry.getKey();
List<WebElement> list = entry.getValue();
// to iterate over the list, you can try
for (int i=0; i < list.size(); ++i) {
WebElement we = list.get(i);
// do something with this web element
}
}
My intention is to iterate through all the WebElements within the Value of one Key within map
That should be easy enough:
for( WebElement element : map.get(key) ) {
//do whatever is appropriate
}
There's one problem with the above: if get(key) returns null (either the key is not mapped or the map contain's the value null for that key) you get a NullPointerException. To fix that could first get the map, check if you didn't get null, then iterate:
List<WebElement> list = map.get(key);
if( list != null ) {
for( WebElement element : list ) {
//do whatever is appropriate
}
}
You might also want to have a look at Guava's ListMultimap, which always will return a collection/list on get() and makes handling maps with list values a lot easier.
Will "entry.getValue().size()" get the Size of the List in that case?
Yes since entry.getValue() should return a List unless you mapped null for the given key. And since you get a List the call to size() will return the list's size.
And how may I get a certain item out of the list in such a case?
If you know the index of that element just check whether the list actually contains that index, i.e. whether index >= 0 && index < list.size(). Then just get it with list.get(index).
If you don't know the index you need to iterate over the list and inspect each element until you reach the end or found the element you need. Alternatively, if you can sort the list by the property you're checking, you could also use binary search to locate the element, if it exists.
Note, though, that LinkedList has linear cost for get(index) and thus isn't well suited for getting by index or binary search, at least not if the list contains many elements.

How to keep the N highest values?

I'm doing a method that takes the value from a lot of objects with double getDelay(). But I need some help because I don't know how to save the 6 higher values. I thought to make a loop and save values in an array but I don't know how to insert a new value and delete the smallest and reordering the array. Any suggestions to save and order the values?
EDIT:
Thanks to all, I forgot to say that I have to save the object (or the name in a String with getName(), I don't care) too. I thought use queues but I don't control them a lot. How can I order it? Because if I use Array.sort I don't know of what objects are this values
You can just use Arrays.sort(yourArr) and then take the last N entries.
See answer: Java - Ordering array values from highest to lowest
You can add all values in an double[] array. Then use Arrays.sort() like this:
Arrays.sort(array,Collections.reverseOrder()); // this will sort array in descending order
Now you can access first 6 elements of this array to get largest 6 values.
EDIT: If you want to keep objects as well, you can use TreeMap<Double,Object>. Populate it with ids and objects. The elements in TreeMap are sorted by key which is Double here.
You can then retreive last 6 elements in TreeMap like this:
List<Object> highest = new ArrayList<Object>;
for(int i=0; i<6; i++){
Double last = treemap.getLastKey();
Object objLast = treemap.get(last);
hightest.put(objLast);
treemap.remove(last);
}
Note: I have used ArrayList to store objects with highest double if you want to keep both you can instead use Map implementation to save both double and Object. Hope this helps.
You'll actually want to create a Comparator<MyObject> and sort an array of MyObject directly:
Comparator<MyObject> myComparator = (o1, o2) -> {
o1.getDelay() > o2.getDelay() ? -1 : (o1.getDelay() < o2.getDelay() ? 1 : 0);
} // Reverse order by getDelay()
MyObject[] stuff;
Arrays.sort(stuff, myComparator);
for (int i = 0; i < 6; i++) {
doSomething(stuff[i]);
}

Find indices of common elements in arraylists in java

I have several ArrayLists with no repeated elements. I want to find their intersection and return indices of common elements in each arraylist.
For example, if I have input as {0,1,2},{3,0,4},{5,6,0}, then I want to return {0},{1},{2} i.e. indices of common element 0 here.
One way I can think of is to use succesive retainAll() on all ArrayLists to get intersection, and then finding indices of elements of intersection using indexOf() for each input ArrayList.
Is there a better way to do that ?
Sorting the list first would require at least O(nlogn) time. If you are looking for a more efficient algorithm you could get O(n) using hashmaps.
For example with
A=[0,1,2],B=[3,0,4],C=[5,6,0]
You can loop through each list and append elements with a hash on the element. The final hash will look like
H = {0:[0,1,2], 1:[1], 2:[2], 3:[0], 4:[2], 5:[0], 6:[1]}
Here, the key is the element, and the value is the index in it's corresponding list. Now, just loop through the hashmap to find any lists that have a size of 3, in this case, to get the indices.
The code would look something like this (untested):
int[][] lists = {{0,1,2}, {3,0,4}, {5,6,0}};
// Create the hashmap
Map<Integer, List<Integer>> H = new HashMap<Integer, List<Integer>>();
for(int i = 0; i < lists.length; i++){
for(int j = 0; j < lists[0].length; j++){
// create the list if this is the first occurance
if(!H.containsKey(lists[i][j]))
H.put(lists[i][j], new ArrayList<Integer>());
// add the index to the list
H.get(lists[i][j]).add(j);
}
}
// Print out indexes for elements that are shared between all lists
for(Map.Entry<Integer, List<Integer>> e : H.entrySet()){
// check that the list of indexes matches the # of lists
if(e.getValue().size() == lists.length){
System.out.println(e.getKey() + ":" + e.getValue());
}
}
EDIT: Just noticed you suggested using retainAll() in your question. That would also be O(n).
Here is a very inefficient but fairly readable solution using streams that returns you a list of lists.
int source[][];
Arrays.stream(source)
.map(list -> IntMap.range(0, list.length)
.filter(i -> Arrays.stream(source)
.allMatch(l -> Arrays.binarySearch(l, list[i]) >= 0))
.collect(Collectors.toList()))
.collect(Collectors.toList());
You can add toArray calls to convert to arrays if required.

How to Iterate through List of Objects, passing to method then store return value in array list?

I want to iterate through a List of Team objects, each object has a string and three integers within it. I want to pass it to a method which will compare the first Team object with the second one, then second to third and so on, Then finally get the returned enumerator depending on the comparison and store it into an array list.
This is what I have so far, but when I run it, it comes up with a null value exception.
TeamList = leagueRepository.getTeamList();
int i = 0;
for(Team team: teamList) {
TeamStatus teamStatus = team.leagueStatus(team, team);
verdictArray.add(i, teamStatus);
How do I get the first and second Team objects in the List?
If TeamList is a List you can call get(0) to get the first entry and get(1) to get the second entry.
If you only want to sort the list you can take a look at this post
Java List Sorting: Is there a way to keep a list permantly sorted automatically like TreeMap?
To get the first and second objects in a list, you should use list.get(0) and list.get(1).
The simplest way is to iterate using an index:
for (int i = 0; i < list.size() - 1; i++) {
Team current = list.get(i);
Team next = list.get(i + 1);
// do something with current and next
}
You could also store the previous element at each iteration:
Team previous = null;
for (Team current : list) {
if (previous != null) {
// do something with previous and current
}
previous = current;
}
It's nothing but sorting. If youe use Collections.sort with comparator you can achieve this.

Categories