Проверьте, все ли элементы в списке имеют одинаковое логическое значение

#java #arraylist

#java #arraylist

Вопрос:

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

Если объект вступает в контакт с другим объектом в ArrayList, он установит логическое значение, вызываемое visible из true to false .

Есть ли способ проверить, все ли экземпляры элементов в ArrayList были установлены в false through:

 XXXX.visible = false
  

Как только я смогу проверить, все ли они установлены false .

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

1. list.stream().allMatch

2. bool allBricks = true; for(GameObj brick : yourList) { if(brick.visible) { allBricks = false; break; } } if(allBricks) { System.out.println("Well Done, Game over."); }

3. В таких сценариях, как этот, другой подход заключается в том, чтобы иметь счетчик, например int bricksHits , который увеличивается при попадании кирпича. Затем вы можете использовать простой оператор if, такой как if(bricksHit >= totalBricks) { ... } , который проверяется только один раз, а не перебирать весь список (в худшем случае).

4. Да, давайте предложим решение для функционального программирования новичку в Boolean and ArrayList .

Ответ №1:

Вы можете использовать Stream.noneMatch() для этого:

 if (bricks.stream().noneMatch(GameObj::isVisible)) {
    doStuffIfAllBricksAreInvisible();
}
  

Это возвращает true, если все блоки невидимы.

Кроме того, я бы рекомендовал взглянуть на Stream.allMatch() , который возвращает true, если все элементы списка соответствуют заданному предикату.

Использование allMatch() этого будет выглядеть следующим образом:

 if (bricks.stream().allMatch(b -> !b.isVisible())) {
    doStuffIfAllBricksAreInvisible();
}
  

Чтобы завершить это, вы также можете взглянуть на Stream.anyMatch() , который возвращает true, если один из элементов соответствует заданному предикату.

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

1. @HBU Вы должны настроить эту часть в соответствии с вашими потребностями в вашем gameObj. Не могли бы вы добавить это к своему вопросу? Я также обновил свой пост.

2. Не используйте общедоступные поля, лучше создайте для него средство получения. В качестве альтернативы вы можете использовать b -> b.visible вместо ссылки на метод.

3. Это догматическая Java, но это не имеет смысла. Если у вас есть что-то, что должно быть общедоступным, удалите шаблонный код и сделайте его общедоступным. Аргумент о том, что абстракция имеет смысл, поскольку вы можете изменить реализацию getIsVisible , на самом деле никогда не выполняется. Единственное место, где я бы использовал этот шаблонный код, — это при взаимодействии с библиотекой, поведение которой работает с помощью таких методов, как Hibernate. Худшими являются POJOs, воплощение запоминания решения и неправильного его применения вместо написания чистого кода.

Ответ №2:

Если вы используете Java <8, одним из способов будет сохранить размер arraylist при инициализации в переменной (скажем, имя переменной — count ).

При изменении флага с true на false уменьшите количество на 1. Если значение flag уже равно false, ничего не делайте. Теперь вы можете просто проверить, равно ли количество 0 или нет.

Если количество равно 0, выведите «Молодец, игра окончена» или продолжайте игру.

Для Java 8 или выше вы можете использовать streams API, как предложено в других ответах.

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

1. Просто будьте осторожны с подобным решением, поскольку каждый экземпляр изменяет одну и ту же переменную, и, скорее всего, потребуется потокобезопасное решение.

Ответ №3:

Я предлагаю использовать anyMatch, потому что метод allMatch возвращает true, когда список пуст

 if (!bricks.stream().anyMatch(GameObj::isVisible)) {
    // TODO when visible balls not found (all are invisible)
}
  

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

1. Хотя вы правильно подметили, все будет зависеть от его варианта использования, потребностей в скорости и дизайна. Например, он может захотеть List , чтобы возвращалось значение empty true или false , или может быть гарантировано, что оно никогда не будет пустым. Что касается скорости, которая часто играет важную роль в игровом дизайне, простой цикл for с a break намного быстрее, чем функциональное решение. Общеизвестно, что функциональный интерфейс Java намного медленнее, чем перебор альтернатив при работе с небольшим ArrayList .

Ответ №4:

Проверьте List , все ли boolean значения true или хотя бы одно значение равно false

         List<Boolean> booleans = new ArrayList<>();
            
        booleans.add(false);
        booleans.add(true);
        booleans.add(true);
        booleans.add(true);
            
        boolean areAllTrue = booleans.stream().allMatch(Boolean::booleanValue);
        // equivalent to:
        boolean areAllTrue = booleans.stream().allMatch(b -> b);
  

Важное примечание: If booleans.size() равно нулю; результат allMatch() всегда true . Итак, вы должны сначала проверить размер или в зависимости от ваших потребностей контекста.

Ответ №5:

Если вы новичок в Java, вы, вероятно, захотите использовать цикл for, подобный этому:

 bool allFalse = true;
for(int index = 0; index < arrayList.size();   index)
    if(arrayList[index].visible) {
        allFalse = false;
        break;
    }
  

break; завершает цикл for, как только вы найдете первое истинное значение, поскольку вам больше не нужно проверять.

Это сработает, если вы знаете arrayList , что оно не пустое, но может иметь смысл иметь allFalse значение false для пустого List , поскольку то, чего там нет, не является ни true, ни false .

Для проверки чего-либо в an ArrayList с небольшим количеством элементов цикл for с a break также будет значительно быстрее, чем a Stream . Хотя это может и не иметь значения в целом, где читаемость и удобство обслуживания имеют первостепенное значение, в играх это часто имеет значение, особенно если он часто выполняет эту проверку. Однако это зависит от его варианта использования. Скорость может быть не важна.