#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]]