JAVA 8 фильтр списка объектов с любым подходящим свойством - PullRequest
2 голосов
/ 05 марта 2020

Мое требование - отфильтровать список объектов по строке, соответствующей любому из свойств. Например, допустим, у класса Contact есть три свойства: улица, город, телефон.

Я знаю, как работает потоковый фильтр java, где мне нужно сравнить входную строку с каждым свойством, как показано ниже :

contactList.stream().filter(contact -> contact.getStreet().equals("dubai") || 
                            contact.getCity().equals("dubai") || .......).collect(Collectors.toList());

Однако, если класс имеет 20+ свойств и размер списка 80 000+, сравнение каждого свойства с входной строкой повлияет на производительность. Итак, мой вопрос: Java или любая другая библиотека поддерживает фильтрацию списка с любым подходящим свойством? Что-то как показано ниже:

contactList.stream().filter(contact -> contact.anyProperty.equals("dubai").collect(Collectors.toList());

Может кто-нибудь помочь мне в этом, спасибо.

Ответы [ 6 ]

4 голосов
/ 05 марта 2020

Это можно решить с помощью отражения, чтобы прочитать все свойства класса

или

Переопределив метод toString () и проверить, содержит ли результат для String входную строку

3 голосов
/ 05 марта 2020

Один из возможных способов - переопределить toString() необходимыми свойствами и использовать его, чтобы проверить, содержит ли оно слово,

contactList.stream()
    .filter(contact -> contact.toString().contains("dubai"))
    .collect(Collectors.toList());

. Вы также можете использовать Pattern, чтобы найти точное слово .

1 голос
/ 05 марта 2020

Вы можете использовать findAny. Это закончится, как только будет найден кандидат:

Optional<Contact> contact = contactList.stream().filter(contact -> contact.getStreet().equals("dubai") || 
                        contact.getCity().equals("dubai") || .......).findAny();

Или если вам нужна информация, только если такой объект существует, используйте anyMatch:

boolean exists = contactList.stream().anyMatch(contact -> contact.getStreet().equals("dubai") || 
                        contact.getCity().equals("dubai") || .......);
0 голосов
/ 05 марта 2020

Вы можете создать список функций, которые извлекают свойства, чем использовать его в методе фильтра:

List<Function<Contact, Object>> getPrperties = Arrays.asList(
        Contact::getStreet, 
        Contact::getCity
        // other
        );

contactList.stream()
        .filter(contact -> getPrperties.stream()
                .map(f -> f.apply(contact))
                .anyMatch("dubai"::equals)
        )
        .collect(Collectors.toList();

Или вы можете извлечь метод теста:

BiFunction<Contact, String, Boolean> test = (contact, values) ->
        getPrperties.stream().map(f -> f.apply(contact)).anyMatch(values::equals);

List<Person> collect = contactList.stream()
        .filter(contact -> test.apply(contact, "dubai"))
        .collect(Collectors.toList());
0 голосов
/ 05 марта 2020

Полагаю, код, заблокированный вашей проблемой, решен.

contactList.stream().anyMatch(contact -> contactMacther(contact,"dubai"));
private boolean contactMacther(Contact contact, String match){
    return contact.getStreet().equalsIgnoreCase(match) ||
            contact.getCity().equalsIgnoreCase(match);
0 голосов
/ 05 марта 2020

У меня есть проект, который использует Gson и JSON, когда я читаю ваш вопрос, первое, о чем я думаю:

  1. Преобразование вашего списка в JsonArray из JsonObject => Вы можете легко получить набор ключей каждого JsonObject (список свойств вашего контактного объекта)
  2. Фильтровать в этом списке, найти все JsonObject со значением "dubai"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...