1

Is there a way to choose first key from a hashmap that meets certain condition?

As part of my coursework I need to write a battleship "game".

I have two hashmaps, one with encounters that ships can fight in and another one with all the ships. Encounter and ships have battle level and the one with higher battle skill wins.

The problem I'm having is that user is only allowed to enter encounter no. in which he wants to fight. Once encounter is chosen, it then should select a random ship from the hashmap, see if the ship can fight in that encounter type(not every ship can fight in every encounter) and if it can then it compares the battle skill and returns final result.

Basically I dont know make my program select a first key from my hashmap and if that one cant fight then it selects next one until it finds one that can fight.

public String fightEncounter(int encNo)
{                     
    String s = "";
    if ( encounterList.get(encNo) != null)
    {
        if (!allActiveShips.isEmpty())
        {
            if ( canFight(encNo) == true)
            {
                for (Ship sh : allActiveShips.values())
                {
                if (encounterList.get(encNo).getSkillReq() < allActiveShips.get(sh).getBattleSkill())
                {
                        s = s + (" Encounter won by : " + s.toString());
                        chest = chest + encounterList.get(encNo).getPlunder();
                        sh.setShipState(ShipState.RESTING);
                }        
                else if ( allActiveShips.isEmpty() )
                {
                        s = s + (" Encounter lost as no ships available ");
                        chest = chest - encounterList.get(encNo).getPlunder();
                }   
                else if ( encounterList.get(encNo).getSkillReq() > allActiveShips.get(sh).getBattleSkill() )
                {
                        s = s + (" Encounter lost on battle skill leve and " + sh.getShipName() + " sunk ");
                        chest = chest - encounterList.get(encNo).getPlunder();
                        sh.setShipState(ShipState.SUNK);
                        if ( isDefeated() == true )
                        {
                            s = s + (" You have been defeated");
                        }
                }
            }
            }
            else
            {
                    return("CANT FIGHT");  
            }

        }
        else 
        {
            return("No ship to available");
        }
    }  
    return s;
}

I have also written a private method in the same class which checks if Ship can fight in chosen encounter and that's the method I can't write :

private boolean canFight(int encNo)      
{
        if ( encounterList.containsValue(encNo))
        {
            for (Ship s : allActiveShips.values())
                {
                if (s.getShipType() == "ManOwar" && encounterList.get(encNo).getEncounterType() == EncounterType.BATTLE && encounterList.get(encNo).getEncounterType() == EncounterType.BLOCKADE )
                {
                    return true;
                }
                else if (s.getShipType() == "Sloop" && encounterList.get(encNo).getEncounterType() == EncounterType.BATTLE && encounterList.get(encNo).getEncounterType() == EncounterType.SKIRMISH )
                {
                    return true;
                }
                else if (s.getShipType() == "Frigate" && ((Frigate)s).isPinnace() == true )
                {
                    return true;
                }
                else if (s.getShipType() == "Frigate" && encounterList.get(encNo).getEncounterType() == EncounterType.BATTLE && encounterList.get(encNo).getEncounterType() == EncounterType.SKIRMISH )
                {
                    return true;
                }
            }   
        }
        return false;
   }
MikeyD
  • 37
  • 6

2 Answers2

2

Let's say the key is of type Ship and there is a predicate function

boolean testConditionOn(Ship key) {...}

Java7 and before

Ship foundShip = null;
for (Ship ship : ships.keySet()) {
   if (testConditionOn(ship)) {
      foundShip = ship;
      break;
   }
}
// Do what you need with the foundShip

Java8

Optional<Ship> foundShip = 
   ships.keySet().stream().filter(key -> testConditionOn(key)).findFirst();
if (foundShip.isPresent()) {
   Ship theShip = foundShip.get();
   // do what you need with theShip
}    
T.Gounelle
  • 5,953
  • 1
  • 22
  • 32
  • I'm receiving an error String cannot be converted to Ship on testConditionOn(key) – MikeyD Mar 04 '15 at 17:14
  • Check if you copied a `String` instead of `Ship`. I edited my answer when you posted the code and I saw the key was a `Ship`. The `testConditionOn(Ship s)` is a function **you** have to defined according to your need. And you can name it as you want ;) – T.Gounelle Mar 04 '15 at 17:18
0

This should print either "42" or "34", depending on the order in which the keys are iterated over. HashMap does not guarantee any ordering.

import java.util.HashMap;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        Map<String, String> source = new HashMap<>();
        source.put("fourty two", "42");
        source.put("thirty four", "34");

        for(String key : source.keySet()) {
            if (key.contains("four")) {
                System.out.println(source.get(key));
                break;
            }
        }
    }
}
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60