如何根据其他属性值从列表中移除元素?

huangapple go评论61阅读模式
英文:

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, &quot;Jon&quot;, &quot;TODO&quot;);
        Person p2 = new Person(2, &quot;Doe&quot;, &quot;TODO&quot;);
        Person p3 = new Person(3, &quot;Jon&quot;, &quot;DONE&quot;);
        Person p4 = new Person(4, &quot;Jane&quot;, &quot;TODO&quot;);
        Person p5 = new Person(5, &quot;Doe&quot;, &quot;DONE&quot;);

        List&lt;Person&gt; persons = new ArrayList&lt;&gt;();
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        persons.add(p4);
        persons.add(p5);

        persons.removeIf(p -&gt; p.getStatus().equalsIgnoreCase(&quot;done&quot;));
        persons.forEach(p -&gt; {
            System.out.println(p.getName()  +  &quot;#&quot; + 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 -&gt; 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&lt;String, Person&gt; 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&lt;Person&gt; notDone = persons.stream()
    .collect(
        Collectors.groupingBy(
            Person::getName,
            Collectors.collectingAndThen(Collectors.toList(), list -&gt; list.get(list.size() - 1))
        )
    )           // here we have a Map&lt;String, Person&gt;
    .values()   // then a Set&lt;Person&gt;
    .stream()   // then a Stream&lt;Person&gt;
    .filter(p -&gt; !p.getStatus().equalsIgnoreCase(&quot;done&quot;))
    .collect(Collectors.toList());

huangapple
  • 本文由 发表于 2020年8月28日 05:23:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63624347.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定