Поиск значений в массиве ArrayList в другом массиве ArrayList

#java #arrays #arraylist

#java #массивы #arraylist

Вопрос:

У меня есть два разных ArrayList экземпляра, один из type Container и один из type String . Первый — это список «запрещенных товаров» (строк) для страны, а другой — список контейнеров на судне. Корабль путешествует по стране, и в контейнерах производится поиск запрещенных товаров. Если в контейнере contains запрещенные товары, этот контейнер следует удалить / удалить.

 public Customs(String country)
{
    countryName = country;
    bannedGoods = new ArrayList<String>();
}

public Ship(String n, double weight)
{
    emptyWeight = totalWeight = weight;
    name = n;
    containers = new ArrayList<Container>();
}    
  

У меня уже есть метод в классе Ship, который удаляет контейнер:

 public void removeContainer(int i) 
{
    if(i >= 0 amp;amp; i < containers.size()) {
        Container r = containers.remove(i);
        totalWeight = totalWeight - r.getWeight();
    }       
}
  

Я пытаюсь создать метод для inspect отправки контейнеров. Я хочу использовать два цикла for для каждого из массивов, но, похоже, я не могу понять это правильно! Может кто-нибудь помочь мне использовать два цикла для поиска в массивах? Кроме того, я думаю, что мне нужно будет использовать итератор ( remove в частности, функцию) в цикле, но это также сбивает меня с толку. Должен remove ли метод итератора заменить метод, который я уже написал в class ship? Вот что у меня есть:

 public void inspect(Ship ship) 
{
    for (String good : bannedGoods) {
        for (String con : containers) {
            if (con.contains(good) {
                container.remove();
            }
        }
    }
  

И вот моя попытка итератора:

 for(String good : bannedGoods) {
    Iterator<String> it = ship.containers.iterator();
        while (it.hasNext())
            if (ship.contains(good))
                it.remove();
}
  

Ответ №1:

Я не думаю, что вам нужно 2 цикла for. Вы должны перебирать запрещенные товары и просто удалять их из контейнеров.

Кроме того, предполагая, что containers список имеет тип string , как это указано в вашей первой строке : I have two different arrayLists of the same type String

 public void inspect(Ship ship, ArrayList<String> bannedGoods){
    if (ship == null || bannedGoods == null || bannedGoods.isEmpty())
        return;
    for(String good : bannedGoods){
        ship.containers.remove(good);
    }
}
  

Если, Containers имеет тип Container и содержит список контейнеров (Arraylist of string) , который доступен с помощью метода get_containers() , будет работать следующее:

 public void inspect(Ship ship, ArrayList<String> bannedGoods){
    if (ship == null || bannedGoods == null || bannedGoods.isEmpty())
        return;
    for(String good : bannedGoods){
        for(Container container : ship.containers){
            container.get_containers().remove(good);
        }
    }
}
  

Комментарии:

1. containers это список Container объектов, а не строк. Также inspect предположительно является методом экземпляра Customs , поэтому он имеет прямой доступ к bannedGoods списку.

2. OP записал это как первую строку : I have two different arrayLists of the same type String

3. Может показаться, что второй список находится внутри Container . См . Конструктор ship, containers = new ArrayList<Container>(); .

4. Да, извините! Один массив имеет тип String, а другой — тип Container . Извините за ошибку! Я отредактировал свой пост.

5. @SamStan Это отвечает на ваш вопрос?

Ответ №2:

Вы можете придерживаться тех методов, которые используете в данный момент. Но имейте в виду, что вам нужно либо использовать метод удаления итератора, либо не использовать итераторы. Итак, чтобы использовать ваш метод удаления, либо реализуйте Iterable , либо просто используйте индексы вместо итераторов:

 for (int i = 0; i < bannedGoods.size(); i  )
{
    for (int j = 0; j < containers.size();) // NOTE: no j   here
    {
        Container c = containers.get(j);
        if (c.contains(bannedGoods.get(i))
            c.removeContainer(j);
        else
            j  ; // only if you don't remove the container increment
                 // j - when removing the next element gets current
                 // index
    }
}
  

Ответ №3:

На самом деле вы довольно близки к этому, и вы проделали хорошую работу, сосредоточив внимание на принципах объектно-ориентированного программирования при разработке своих классов. Я думаю, что сейчас вам нужно сосредоточиться на том, чтобы быть более осторожным с вашими типами. Ниже приведены некоторые предлагаемые изменения в ваших классах ( Container не показаны, но я предполагаю, что у него есть public boolean contains (String s) метод, который проверяет, есть ли в контейнере определенный товар s внутри.

 import java.util.*;

public class Ship implements Iterable<Container> {
    private double emptyWeight, totalWeight, weight;
    private String name;
    private List<Container> containers = new ArrayList<Container>();

    public Ship(String n, double weight) {
        emptyWeight = totalWeight = weight;
        name = n;
    }

    private void removeContainer(int i) {
        if (i >= 0 amp;amp; i < containers.size()) {
            Container r = containers.remove(i);
            totalWeight = totalWeight - r.getWeight();
        }       
    }

    public Iterator<Container> iterator() {
        return new Iterator<Container> {
            private index = 0;
            private Container previous = null;

            public boolean hasNext() {
                return index < containers.size();
            }

            public Container next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();
                }
                previous = containers.get(index  );

                return previous;
            }

            public void remove() {
                if (previous == null) {
                    throw new IllegalStateException();
                }

                removeContainer(containers.indexOf(previous));

                previous = null;
            }
        };
    }
}
  

Я предлагаю removeContainer придерживаться вашего Ship класса, поскольку он отвечает за отслеживание того, как изменяется его вес при удалении контейнера. По той же причине не разрешайте внешним классам напрямую обращаться к своему containers списку. Таким образом, вы можете запретить другому коду добавлять или удалять значения из этого списка без weight правильного обновления. Я бы предложил сделать containers список закрытым и предоставить Iterator возможность пользователям класса взаимодействовать с контейнерами.

В вашем Customs классе вы бы использовали метод Iterator ‘s remove для удаления Container экземпляров, вызывающих нарушения:

 import java.util.*;

public class Customs {
    private String countryName;
    private List<String> bannedGoods = new ArrayList<String>();

    public Customs(String country) {
        countryName = country;
    }

    public void inspect(Ship ship) {
        for (String good : bannedGoods) {
            for (Iterator<Container> it = ship.iterator(); it.hasNext();) {
                Container container = it.next();

                if (container.contains(good) {
                    it.remove();
                }
            }
        }
    }
}