Работа с внутренним списком, содержащим элемент с определенным значением свойства, Java 8 - PullRequest
0 голосов
/ 03 октября 2019

Я создал код для конкретной задачи. Но, я думаю: должен иметь лучший способ сделать этот код.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class InnerListContainingItemWithSpecificPropertyValue {

  public static void main(String[] args) {

    List<List<Person>> nestedPersonList = Arrays.asList(
        Arrays.asList(new Person("a0", 0), new Person("b0", 1)), //0
        Arrays.asList(new Person("a1", 0), new Person("b1", 1)), //1
        Arrays.asList(new Person("a2", 0), new Person("b2", 1)), //2
        Arrays.asList(new Person("a3", 0), new Person("b3", 1)) // 5
    );

    List<List<Person>> outNestedPersonList = new ArrayList<>();

    nestedPersonList.stream().flatMap(List::stream).forEach(outerPerson -> {

      //Determine if Exist Some inner List
      boolean ageFound = outNestedPersonList
          .stream()
          .flatMap(List::stream)
          .filter(innerPerson -> outerPerson.getAge() == innerPerson.getAge())
          .count() > 0L;

      List<Person> listPersonWithAge;
      if (!ageFound) {
        listPersonWithAge = new ArrayList<>();
        outNestedPersonList.add(listPersonWithAge);
      } else {
        // Get the Inner List with Specific Property Value
        listPersonWithAge = outNestedPersonList
            .stream()
            .filter(innerListPerson -> {
              return innerListPerson
                  .stream()
                  .filter(innerPerson -> outerPerson.getAge() == innerPerson.getAge())
                  .count() > 0L;
            }).findFirst().get();

      }
      listPersonWithAge.add(outerPerson);
      // Do something
      if (listPersonWithAge.size() == 4) {
        System.out.println("listPerson with age:" + outerPerson.getAge() + "\twill be removed!");
        outNestedPersonList.remove(listPersonWithAge);
      }

    });

  }

  public static class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
      this.name = name;
      this.age = age;
    }

    public String getName() {
      return name;
    }

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

    public int getAge() {
      return age;
    }

    public void setAge(int age) {
      this.age = age;
    }

    @Override
    public int hashCode() {
      int hash = 5;
      hash = 73 * hash + Objects.hashCode(this.name);
      hash = 73 * hash + this.age;
      return hash;
    }

    @Override
    public boolean equals(Object obj) {
      if (this == obj) {
        return true;
      }
      if (obj == null) {
        return false;
      }
      if (getClass() != obj.getClass()) {
        return false;
      }
      final Person other = (Person) obj;
      if (this.age != other.age) {
        return false;
      }
      if (!Objects.equals(this.name, other.name)) {
        return false;
      }
      return true;
    }

    @Override
    public String toString() {
      return "Person{" + "name=" + name + ", age=" + age + '}';
    }

  }

}

вывод:

listPerson with age:0   will be removed!
listPerson with age:1   will be removed!

В качестве альтернативы мой код:

  1. Как узнать, существует ли внутренний список, содержащий какой-либо элемент с некоторым значением свойства?
  2. Как получить внутренний список с этим элементом?
  3. Если внешний список не содержитвнутренний список, как его создать?

1 Ответ

0 голосов
/ 03 октября 2019

Первый шаг улучшения вашего кода - избегать использования flatMap. Упрощается работа с вложенными данными, но вы пытаетесь работать с одним из подсписков, а не со всеми людьми в целом.

Вы пытаетесь оперировать одним подсписком, а невсе люди во всех списках, поэтому вместо использования flatMap вы можете вложить два набора потоковых операций.

listOfListOfPeople.stream()
  // filter out sublists that don't have anyone with the target age
  .filter(sublist ->
    // Check if the nested list contains anyone with the given age
    sublist.stream()
      .anyMatch(p -> p.age == targetAge))
  // get one sublist out of the stream
  .findAny()
  // if there wasn't one, get an empty list
  .orElse(Collections.emptyList());

Если вы хотите изменить пустой список, вы получите, еслинет людей с целевым возрастом, замените последнюю строку на что-то вроде .orElseGet(ArrayList::new).

...