У меня есть метод, который нужно реализовать, который просит меня вернуть корабль в очереди в соответствии с некоторыми условиями

/** 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;
        }
    }

Я застрял при возврате корабля в инструкции if else в цикле for. А также как я могу узнать, если условие, например, carrying dangerous cargo = NauticalFlag.BRAVO, имеет более одного корабля в очереди и возвращает ли тот, который был добавлен в очередь первым.

0
HY2000 11 Окт 2021 в 12:41

2 ответа

Лучший ответ

Вы должны каждый раз перебирать очередь и искать флаги по приоритету, вот способ сделать это чисто:

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();
}
1
Yassir Khaldi 11 Окт 2021 в 10:51

Я бы сделал это как линейный поиск алгоритма минимизации, например:

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;
    }
}
0
Christopher 11 Окт 2021 в 13:26