I have a method need to implement which ask me to return the ship in a queue according to some conditions
/** Returns the next ship waiting to enter the port. The queue should not change.
*
* The rules for determining which ship in the queue should be returned next are as
* follows:
* <ul>
* <li>If a ship is carrying dangerous cargo, it should be returned. If more than one
* ship is carrying dangerous cargo return the one added to the queue first.</li>
*
* <li>If a ship requires medical assistance, it should be returned. If more than one
* ship requires medical assistance, return the one added to the queue first.</li>
*
* <li>If a ship is ready to be docked, it should be returned. If more than one ship is
* ready to be docked, return the one added to the queue first.</li>
*
* <li>If there is a container ship in the queue, return the one added to the queue first.</li>
*
* <li>If this point is reached and no ship has been returned, return the ship that was
* added to the queue first.</li>
*
* <li>If there are no ships in the queue, return null.</li>
* </ul>
* @return next ship in queue
* */
public Ship peek() {
Queue<Ship> newShips = new LinkedList<>(ships); // Make a copy of the queue and change here
for (Ship s : newShips) {
if (s.getFlag() == NauticalFlag.BRAVO) { //ship carrying dangerous cargo
return s;
} else if (s.getFlag() == NauticalFlag.WHISKEY) { // ship requires medical assistance
return s;
} else if (s.getFlag() == NauticalFlag.HOTEL) { // ship is ready to be docked
return s;
} else if (s.getName() == "ContainerShip") { // Container Ship
return s;
} else {
return poll(); // ship that was added to the queue first
}
}
if (newShips.isEmpty()) {
return null;
}
}
I am stuck on returning the ship in the if else statement in the for loop. And also how can I know if the condition for example carrying dangerous cargo
= NauticalFlag.BRAVO
have more than one ship in the queue and return the one added to queue first.
CodePudding user response:
You must iterate through the queue everytime and look for the flags by priority, this is the way to do it in a clean way:
public Ship peek() {
Queue<Ship> newShips = new LinkedList<>(ships); // Make a copy of the queue and change here
return findFirstShip(newShips, NauticalFlag.BRAVO)
.orElse(findFirstShip(newShips, NauticalFlag.WHISKEY)
.orElse(findFirstShip(newShips, NauticalFlag.HOTEL)
.orElse(findFirstShip(newShips, NauticalFlag.CONTAINER)
.orElseGet(newShips::poll))));
}
private Optional<Ship> findFirstShip(Queue<Ship> newShips, NauticalFlag flag) {
return newShips.stream().filter(ship -> ship.getFlag() == flag).findFirst();
}
CodePudding user response:
I would do this as a linear search of minimization algorithm, like this:
public class Ship
{
/** The known ships. This needs to be populated for the example to work. */
static List<Ship> ships = new ArrayList<> ();
/** Type/status of this ship. */
private NauticalFlag flag;
/** Ship name or type name */
private String name;
public NauticalFlag getFlag ()
{
return flag;
}
public String getName ()
{
return name;
}
/** This is the original version from the question */
public Ship peek1 ()
{
// Make a copy of the queue and change here
final Queue<Ship> newShips = new LinkedList<> (ships);
for (final Ship s : newShips)
{
if (s.getFlag () == NauticalFlag.BRAVO)
{ // ship carrying dangerous cargo
return s;
}
else if (s.getFlag () == NauticalFlag.WHISKEY)
{ // ship requires medical assistance
return s;
}
else if (s.getFlag () == NauticalFlag.HOTEL)
{ // ship is ready to be docked
return s;
}
else if (s.getName () == "ContainerShip")
{ // Container Ship
return s;
}
else
{
return newShips.poll (); // ship that was added to the queue first
}
}
if (newShips.isEmpty ())
{
return null;
}
return newShips.poll ();
}
/** This is how I would do it as a linear search (or minimization). */
public Ship peek2 ()
{
Ship result = null;
for (final Ship s : ships)
{
if (priority (s) > priority (result))
{
result = s;
}
}
return result;
}
/**
* Define the preference function here. Note how null is handled first to prevent
* nullPointerException problems.
*/
public int priority (Ship s)
{
if (s == null)
{
return 0;
}
if (s.getFlag () == NauticalFlag.BRAVO)
{ // ship carrying dangerous cargo
return 5;
}
else if (s.getFlag () == NauticalFlag.WHISKEY)
{ // ship requires medical assistance
return 4;
}
else if (s.getFlag () == NauticalFlag.HOTEL)
{ // ship is ready to be docked
return 3;
}
else if (s.getName () == "ContainerShip")
{ // Container Ship
return 2;
}
return 1;
}
}