Используя лямбда-выражения Java 8, отфильтруйте список объектов по свойству внутреннего списка. - PullRequest
0 голосов
/ 25 августа 2018

Я новичок в лямбда-выражениях Java и борюсь со следующей проблемой:

Я пытаюсь отфильтровать следующий список объектов действия до одного действия ссамое последнее время начала:

{
     Name: "activity1"
     Id: "abc-123"
     Fields: [
          { key: "startTime", value: "2018-08-24T12:00:01" },
          { key: "foo", value: "bar" },
          { key: "baz", value: "zoop" }
     ]
},
{
     Name: "activity2"
     Id: "def-456"
     Fields: [
          { key: "bat", value: "zap" },
          { key: "startTime", value: "2018-08-23T12:00:01" },
          { key: "cat", value: "dog" }
     ]
},
{
     Name: "activity3"
     Id: "ghi-789"
     Fields: [
          { key: "flim", value: "flam" },
          { key: "boop", value: "bop" },
          { key: "startTime", value: "2018-08-22T12:00:01" }
     ]
}

По сути, каждый объект имеет внутренний список полей, которые отображаются в произвольном порядке, и я хочу отфильтровать родительскую коллекцию до одного элемента на основе «startTime»поле с максимальной датой.

Для данных примера цель состоит в том, чтобы возвратить только объект с именем "activity1".Обратите внимание, что объекты Field отображаются в моих данных не в определенном порядке.Кроме того, если startTime для действия совпадает с другим действием, код должен брать тот элемент, который находится первым в коллекции.

Предполагается, что действия и поля находятся в Списке, и есть получатели / установщики наМой класс «Активность» - это то, с чего я начал, но я знаю, что это неправильно:

activities().stream().filter(activity ->  
    activity.getFields().stream()
            .filter(field -> field.getKey().equals("startTime"))
            .max((field1, field2) -> {
                Date date1 = Date.from(Instant.parse(field1.getValue()));
                Date date2 = Date.from(Instant.parse(field2.getValue()));
                return date1.compareTo(date2);
            }).isPresent()
).findAny().get();

Любая помощь или пример того, как мне следует подойти к этому, была бы очень признательна.Спасибо!


Edit-1: Фактические классы Activity и Field, с которыми я работаю, извлекаются из сторонней библиотеки и не принадлежат моимсобственный дизайн.Вот идея того, как они выглядят:

public class Activity {
     private String id;
     private String name;
     private List<Field> fields;

     public String getId() {
         return id;
     }

     public void setId(String id) {
         this.id = id;
     }

     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }

     public List<Field> getFields() {
         return fields;
     }

     public void setFields(List<Field> fields) {
         this.fields = fields;
     }
 }

public class Field {
     private String key;
     private String value;

     public String getKey() {
         return key;
     }

     public void setKey(String key) {
         this.key = key;
     }

     public String getValue() {
         return value;
     }

     public void setValue(String value) {
         this.value = value;
     }
 }

1 Ответ

0 голосов
/ 25 августа 2018

Возможно, вы хотите определить функцию, которая извлекает дату, а затем использовать Collectors.maxBy. Например:

// Somewhere in your class:
Instant startDate(Activity activity) {
  return activity.getFields()
    .stream()
    .filter(field -> field.getKey().equals("startTime"))
    .map(field -> Instant.parse(field.getValue()))
    .findAny()
    .get();
}

// .. and then to use it:
Optional<Activity> maxStartDateActivity = activities()
    .stream()
    .max(Comparator.comparing(MyClass::startDate));

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

...