Обновление одного списка на основе другого списка с использованием потока - PullRequest
0 голосов
/ 27 августа 2018

Я хочу обновить элементы в существующем списке из входящего списка.

class Person{
  String id;
  String name;
  String age;
.
.
.
  @Override
  public boolean equals(Object object) {
    return ... ((Person) object).id.equals(this.id);
  }
}

Текущий список короче:

ArrayList<Person> currentList = Arrays.asList(
   new Person("0", "A", 25),
   new Person("1", "B", 35)
);

Полученный список больше, например

ArrayList<Person> updatedList = Arrays.asList(
       new Person("0", "X", 99),
       new Person("1", "Y", 100),
       new Person("2", "C", 2),
       new Person("3", "D", 3),
       new Person("4", "E", 5)
    );

включая элементы (обозначенные id ) из текущего списка.

Я хотел бы заменить все элементы в текущем списке теми же, что и в новом списке.

Таким образом, после преобразования текущий список будет

{ Person(0, "X", 99), Person(1, "Y", 100) }

Можно ли делать только с Stream.

Ответы [ 4 ]

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

При условии, что вы хотите, чтобы элемент currentList был заменен объектом из updatedList, должно работать следующее:

currentList.stream().map((p) -> {
            return updatedList.stream().filter(u -> p.equals(u)).findFirst().orElse(p);
        }).collect(Collectors.toList());
0 голосов
/ 27 августа 2018

Это достигнет того, что вы просите.

 Map<String, Person> collect = updatedList
                               .stream()
                               .collect(Collectors.toMap(Person::getId, Function.identity()));

 currentList = currentList
               .stream()
               .map(Person::getId)
               .map(collect::get)
               .collect(Collectors.toList());

Как упоминал @Holger, делать это для небольшого списка не так уж и элегантно

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

Если currentList всегда является подмножеством updatedList - это означает, что все currentList появятся в updatedList, вы можете сделать следующее:

Set<String> setOfId = currentList.stream()
                                 .map(person -> person.getId()) // exctract the IDs only
                                 .collect(Collectors.toSet());  // to Set, since they are unique

List<Person> newList = updatedList.stream()                     // filter out those who don't match
                                  .filter(person -> setOfId.contains(person.getId()))  
                                  .collect(Collectors.toList());

Если updatedList и currentList значительно различаются - оба могут иметь уникальных личностей, вы должны выполнить двойную итерацию и использовать Stream::map для замены Person. Если не найдено, замените на себя:

List<Person> newList = currentList.stream()
    .map(person -> updatedList.stream()                                       // map Person to
                              .filter(i -> i.getId().equals(person.getId()))  // .. the found Id
                              .findFirst().orElse(person))                    // .. or else to self
    .collect(Collectors.toList());                                            // result to List
0 голосов
/ 27 августа 2018

Да, можно использовать поток,

  1. Найти список идентификаторов, требуемых из currentList
  2. запись фильтра с идентификаторами в первом списке

    List<String> ids = currentList.stream().map(Person::getId).collect(Collectors.toList());
    currentList = updatedList.stream().filter(o -> ids.contains(o.getId()))
                                      .collect(Collectors.toList());
    
...