Поток Java: Список фильтров 1 на основе объектов, присутствующих в списке 2

#java #java-stream

Вопрос:

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

Список 1 состоит из объектов класса CarModel (L1)

 public class CarModel   {
  private String year;

  private String model;

}
 

Список 2 состоит из объектов класса CarData (L2)

 public class CarData   {
  private OffsetDateTime date;

  private List<CarDetails> carDetails;

}


public class CarDetails   {
  private String owner;

  private List<Cars> cars = null;
}


public class Car   {
  private String modelName;

  private String dealership;

}
 

То, чего я пытаюсь достичь, — это фильтр list2 , основанный на Car.modelName list1 сопоставлении » из » с CarModel.model «из list2 «.

Например:

список 1 состоит из 3 объектов:

 carModel1 = { year: 2019, model: BMW-500-7S-150-Z100 }
carModel2 = { year: 2019, model: MERCEDES-700-7S-350-Z100 }
carModel3 = { year: 2018, model: AUDI-100-Q6-350-Z100 }
 

список 2 содержит следующий объект:

 CarData = {
   date: 2-6-2021,
   carDetails: [
   {
     owner: John,
     cars: [ {
          modelName: BMW-500-7S-*-Z100, 
          dealership: Nevada
       },
       {
          modelName:MERCEDES-700-7S-*-Z100, 
          dealership: Daytona
       }
    ]
   }
  ]
}
 

Таким образом, после фильтрации список 1 не будет содержать c3 , так как эта модель не совпадает с modelName in CarData .

Как я могу это сделать?

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

1. Помогите нам помочь вам — пожалуйста, поделитесь некоторыми примерами ввода и результатами, которые вы пытаетесь получить?

2. Каким должен быть ваш результат? Список отфильтрованных Car ов?

3. @JanezKuhar результатом должен быть список отфильтрованных моделей автомобилей,

4. Используйте a Set для сбора этих modelName s, затем отфильтруйте в соответствии с набором.

5. @Mureinik добавил пример для более подробного разъяснения.

Ответ №1:

Сначала вы можете выровнять вложенные списки и извлечь имена моделей автомобилей из списка как a HashSet . :

 Set<String> names = carDataList.stream()
      .flatMap(cd -> cd.getCarDetails().stream())
      .flatMap(det -> det.getCars().stream())
      .map(Car::getModelName())
      .collect(Collectors.toCollection(HashSet::new));
 

Теперь вы можете использовать contains() метод этого набора для фильтрации ваших List<CarModel> :

 models.stream()
     .filter(model -> names.contains(model.getModel()))
     .collect(Collectors.toList())
     .forEach(m -> System.out.println(m.getModel()));
 

Если вам просто нужны имена в списке:

 models.stream()
    .map(CarModel::getModel)
    .filter(names::contains)
    .collect(Collectors.toList())
    .forEach(System.out::println);
 

Ответ №2:

Прежде всего, было бы проще сохранить имя модели в виде регулярного выражения или обработать его для использования в качестве регулярного выражения (например, BMW-500-7S-(.*)-Z100 вместо BMW-500-7S-*-Z100

Предполагая, что мы используем регулярное выражение подобным образом, мы могли бы использовать поток для итерации по всем именам моделей и фильтрации моделей, которых нет в carData :

 List<String> modelNames = carData.getCarDetails().stream()
                                                 .flatMap(e -> e.getCars().stream())
                                                 .map(Car::getModelName)
                                                 .collect(Collectors.toList());
    
List<CarModel> result = carModels.stream()
                                 .filter(carModel ->                                  
                                             modelNames.stream()
                                                       .anyMatch(name -> name.matches(carModel.getModel()))
                                 ).collect(Collectors.toList());
 

Ответ №3:

Попробуй это.

 List<CarModel> list1 = List.of(
    new CarModel("2019", "BMW-500-7S-150-Z100"),
    new CarModel("2019", "MERCEDES-700-7S-350-Z100"),
    new CarModel("2018", "AUDI-100-Q6-350-Z100"));

List<CarData> list2 = List.of(
    new CarData(OffsetDateTime.of(LocalDate.of(2021, 2, 6), LocalTime.of(0, 0), ZoneOffset.UTC),
        List.of(new CarDetails("John", List.of(
            new Car("BMW-500-7S-*-Z100", "Nevada"),
            new Car("MERCEDES-700-7S-*-Z100", "Daytona"))))));

Pattern models = Pattern.compile(list2.stream()
    .flatMap(d -> d.getCarDetails().stream())
    .flatMap(d -> d.getCars().stream())
    .map(c -> c.getModelName().replaceAll("\*", ".*"))
    .collect(Collectors.joining("|")));

List<CarModel> result = list1.stream()
    .filter(m -> models.matcher(m.getModel()).matches())
    .collect(Collectors.toList());

System.out.println(result);
 

выход:

 [CarModel [year=2019, model=BMW-500-7S-150-Z100], CarModel [year=2019, model=MERCEDES-700-7S-350-Z100]]