英文:
How could I remove elements from the list based on other property values?
问题
@Data
@AllArgsConstructor
public class Person {
int id;
String name;
String status;
}
public class PersonHandler {
public static void main(String[] args) {
Person p1 = new Person(1, "Jon", "TODO");
Person p2 = new Person(2, "Doe", "TODO");
Person p3 = new Person(3, "Jon", "DONE");
Person p4 = new Person(4, "Jane", "TODO");
Person p5 = new Person(5, "Doe", "DONE");
List<Person> persons = new ArrayList<>();
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
persons.add(p5);
persons.removeIf(p -> p.getStatus().equalsIgnoreCase("done"));
persons.forEach(p -> {
System.out.println(p.getName() + "#" + p.getStatus());
});
}
}
The above code outputs:
Jon#TODO
Doe#TODO
Jane#TODO
But Jon and Doe were updated to DONE. But since Jane's status is still TODO as there were no DONE updates yet for Jane, the expected output is:
Jane#TODO
英文:
Assuming I have a Person class and a list to track the status updates.
I only need the TODO status to be displayed. I tried with removeIf but think that would not be right here.
@Data
@AllArgsConstructor
public class Person {
int id;
String name;
String status;
}
public class PersonHandler {
public static void main(String[] args) {
Person p1 = new Person(1, "Jon", "TODO");
Person p2 = new Person(2, "Doe", "TODO");
Person p3 = new Person(3, "Jon", "DONE");
Person p4 = new Person(4, "Jane", "TODO");
Person p5 = new Person(5, "Doe", "DONE");
List<Person> persons = new ArrayList<>();
persons.add(p1);
persons.add(p2);
persons.add(p3);
persons.add(p4);
persons.add(p5);
persons.removeIf(p -> p.getStatus().equalsIgnoreCase("done"));
persons.forEach(p -> {
System.out.println(p.getName() + "#" + p.getStatus());
});
}
}
The above code outputs:
Jon#TODO
Doe#TODO
Jane#TODO
But Jon and Doe were updated to DONE. But since Jane status is still TODO as there were no DONE updates yet for Jane, the expected output is:
Jane#TODO
答案1
得分: 1
以下是您可以实现它的一种方法。首先,遍历所有人员并按姓名将条目分组在一起。然后获取每个人的最后一个条目(list -> list.get(list.size() - 1)
)。如果一个人的状态从TODO变为IN_PROGRESS,然后变为DONE,我们想要丢弃前两个状态。
这将给我们一个 Map<String, Person>
,其中键是人员的姓名,值是他们的最后一个条目。我们实际上不太关心这个映射,它只是帮助我们达到目标的一个中间步骤。我们可以使用 values()
方法并对其进行迭代。
现在,我们可以过滤掉已完成的条目,并collect
剩下的内容。
List<Person> notDone = persons.stream()
.collect(
Collectors.groupingBy(
Person::getName,
Collectors.collectingAndThen(Collectors.toList(), list -> list.get(list.size() - 1))
)
) // 这里我们得到一个 Map<String, Person>
.values() // 然后是一个 Set<Person>
.stream() // 然后是一个 Stream<Person>
.filter(p -> !p.getStatus().equalsIgnoreCase("done"))
.collect(Collectors.toList());
英文:
Here's one way you can accomplish it. First, stream over all the people and group together the entries by the person's name. Then take the final entry for each person (list -> list.get(list.size() - 1)
). If a person was TODO, then went to IN_PROGRESS, then became DONE, we want to throw away those first two.
This will give us a Map<String, Person>
which is a map from the person's name to their last entry. We don't really care about the map, it is just a stepping stone to get us where we want to go. We can just take the values()
, and iterate over them.
Now we can filter out the entries which are done, and collect
what's left.
List<Person> notDone = persons.stream()
.collect(
Collectors.groupingBy(
Person::getName,
Collectors.collectingAndThen(Collectors.toList(), list -> list.get(list.size() - 1))
)
) // here we have a Map<String, Person>
.values() // then a Set<Person>
.stream() // then a Stream<Person>
.filter(p -> !p.getStatus().equalsIgnoreCase("done"))
.collect(Collectors.toList());
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论