Примеры Java Stream contains, containsAny и containsAll

Java Stream API поставляется с богатым набором функций набор промежуточных и конечных операций, но Stream API не имеет встроенных методов contains(), containsAll() или containsAny(). В этом руководстве мы напишем простые примеры для создания этих служебных методов и научимся их использовать.

1. Вспомогательные методы: contains(), containsAny(), containsAll()

Давайте быстро рассмотрим список методов, которые мы планируем добавить в служебный класс, который можно использовать для проверки функциональности contains/containsAny/containsAll.

  • Метод contains возвращает значение true, если указанный элемент присутствует в указанном потоке, в противном случае — false.
  • Метод containsAny проверяет наличие указанного элемента(ов) в указанном потоке. Возвращает true, если найден хотя бы один элемент, в противном случае false.
  • Метод containsAll проверяет наличие указанного элемента(ов) в указанном потоке. Возвращает true, если все элементы найдены, в противном случае false.
public class StreamUtils {public static <T> boolean contains(Stream<T> stream, T element){...}public static <T> boolean containsAny(Stream<T> stream, Collection<? extends T> elements){...}public static <T> boolean containsAny(Stream<T> stream, T... elements){...}public static <T> boolean containsAny(Stream<T> stream, Stream<? extends T> elements){...}public static <T> boolean containsAll(Stream<T> stream, Collection<? extends T> elements){...}public static <T> boolean containsAll(Stream<T> stream, T... elements){...}public static <T> boolean containsAll(Stream<T> stream, Stream<? extends T> elements){...}}

2. Реализации методов

Методы contains(any/all) используют методы Stream.anyMatch() и Stream.allMatch() для проверки наличия элементов аргумента. Мы добавляем дополнительные проверки для значений null.

  • Метод anyMatch() проверяет, содержит ли поток хотя бы один элемент, удовлетворяющий заданному предикату. Это терминальная операция короткого замыкания.
  • Метод allMatch() проверяет, удовлетворяют ли все элементы в потоке указанному Predicate. Это терминальная операция короткого замыкания.

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

public final class StreamUtils {private StreamUtils() {// Private constructor to prevent instantiation}public static <T> boolean contains(Stream<T> stream, T element) {Objects.requireNonNull(stream);Objects.requireNonNull(element);return stream.anyMatch(Predicate.isEqual(element));}public static <T> boolean containsAny(Stream<T> stream, Collection<? extends T> elements) {return containsAny(stream, elements.stream());}public static <T> boolean containsAny(Stream<T> stream, T... elements) {return containsAny(stream, Stream.of(elements));}public static <T> boolean containsAny(Stream<T> stream, Stream<? extends T> elements) {Objects.requireNonNull(stream);Objects.requireNonNull(elements);return elements.anyMatch(stream.collect(Collectors.toSet())::contains);}public static <T> boolean containsAll(Stream<T> stream, Collection<? extends T> elements) {return containsAll(stream, elements.stream());}public static <T> boolean containsAll(Stream<T> stream, T... elements) {return containsAll(stream, Stream.of(elements));}public static <T> boolean containsAll(Stream<T> stream, Stream<? extends T> elements) {Objects.requireNonNull(stream);Objects.requireNonNull(elements);return elements.allMatch(stream.collect(Collectors.toSet())::contains);}}

3. Демонстрация

Давайте протестируем вышеприведенные методы с некоторыми фиктивными данными. В этой демонстрации у нас есть список автомобилей. Класс автомобиля:

@Data@AllArgsConstructor@NoArgsConstructorclass Car {String model;String fuel;Integer capacity;}

Для демонстрации мы добавили следующие автомобили в поток. Также мы создали несколько автомобилей, которые нам нужно проверить. Обратите внимание, что мы знаем, что в потоке присутствует только 'car1', поэтому мы можем проверить наши предположения и быть уверенными в реализациях метода.

List<Car> cars = Arrays.asList(new Car("Dacia", "diesel", 100),new Car("Lexus", "gasoline", 300),new Car("Ford", "electric", 200));Car car1 = new Car("Dacia", "diesel", 100); //Present in original listCar car2 = new Car("Ford", "electric", 80);Car car3 = new Car("Chevrolet", "electric", 150);

Начнем с тестирования метода contains().

Assertions.assertTrue( StreamUtils.contains(cars.stream(), car1) );Assertions.assertFalse( StreamUtils.contains(cars.stream(), car2) );

Далее протестируем метод containsAny(). Мы передали аргументы всеми возможными способами, т.е. varargs, collection и даже другой поток.

Assertions.assertTrue( StreamUtils.containsAny(cars.stream(), car1, car2) );Assertions.assertFalse( StreamUtils.containsAny(cars.stream(), car2, car3) );Assertions.assertTrue( StreamUtils.containsAny(cars.stream(), List.of(car1, car2, car3)) ); // collectionAssertions.assertTrue( StreamUtils.containsAny(cars.stream(), Stream.of(car1, car2, car3)) ); // stream

Аналогично протестируйте подход метода containsAll(). Опять же, мы тестируем со всеми видами типов параметров.

Assertions.assertTrue( StreamUtils.containsAll(cars.stream(), car1) );Assertions.assertFalse( StreamUtils.containsAll(cars.stream(), car1, car3) );Assertions.assertTrue( StreamUtils.containsAll(cars.stream(), List.of(car1)) );Assertions.assertFalse( StreamUtils.containsAll(cars.stream(), Stream.of(car2)) );

4. Заключение

В этом коротком руководстве по Java мы создали класс утилиты Java Stream и добавили методы contains, containsAny и containsAll. Мы можем использовать эти методы в коде нашего приложения напрямую, поскольку они были объявлены статическими методами.

Мы также можем ссылаться на реализации методов, если захотим разработать собственные решения.

Исходный код на Github

Прокрутить вверх