简体   繁体   中英

Comparing integer values of 2 or more keys of one hashmap to 2 values in another hashmap

I have two hashmaps (resources and neededResources).
Goal is to reduce the amount of resources hashmap, but that can only happen if it has enough of both resource.

// String = name of resources available
// Integer = amount of resources available
Map<String, Integer> resources = new HashMap<>();
resources.put("gold", 10);
resources.put("silver", 10);
// String = name of resource needed
// Integer = amount of resource needed
Map<String, Integer> neededResources = new HashMap<>();
neededResources.put("gold", 2);
neededResources.put("silver", 3);

In this sample case, it would take resources 3 times since on 4th try there wouldn't be enough silver, gold value doesn't change as well.

I'm a novice at Java. So far I've tried iterating through both of them but it becomes hard to read and my attempts have looked way too difficult for this task.

Take the value from your resources map, substract the value from neededResources and check if it is >=0. This tells you that there were at least as many resources available as needed. If resources were available, update the value. Otherwise dont.

Create a method wrapper in your resources class

public boolean hasResources(String... pResources){
  for(String resourceKey : pResources){
  int newValue = resources.get(pResourceKey) - neededResources.get(pResourceKey);
    if(newValue < 0){
       return false;
    }
  }
  return true;
}

public void takeResources(String... pResources){
  for(String resourceKey : pResources){
  int newValue = resources.get(pResourceKey) - neededResources.get(pResourceKey);
    resources.put(resourceKey, newValue);
  }
}

The key to this problem is that we don't want to modify the resources Map unless we are absolutely sure that it contains all of the resourcesNeeded . Once you learn about Stream s in Java, this problem should simplify.

First, we want to check if the resources Map contains all of the keys in the resourcesNeeded Map , which may or may not already be given information which you haven't mentioned.

resources.keySet().containsAll(neededResources.keySet());

If that condition is false , then we know that there are needed resources that are not available. Otherwise, we can now check if every value in resources is greater than or equal to the value in resourcesNeeded for its respective key:

resources.entrySet()
         .stream()
         .allMatch(entry -> entry.getValue() >= resourcesNeeded.get(entry.getKey()));

If that condition is false , then more resources are needed then are currently available. Otherwise, we can now modify resources , essentially subtracting each respective value in resourcesNeeded :

resources.replaceAll((k, v) -> v - resourcesNeeded.getOrDefault(k, 0)));

The last two statements can be placed inside of a loop to ensure that the minimum amount of resources remain.

I think this might be what you are after. The code can be inserted after your setup code.

Find the number of possible expenditures:

int n = resources.entrySet().stream().mapToInt(entry -> entry.getValue()/neededResources.getOrDefault(entry.getKey(), 0)).min().getAsInt();
System.out.println(n);

Prints 3

Spend it:

resources.replaceAll((k,v) -> v-n*neededResources.getOrDefault(k,0));
System.out.println(resources);

Prints {gold=4, silver=1}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM