当前位置: 首页 > 知识库问答 >
问题:

使用流元素之间的相关性过滤流

傅雪松
2023-03-14

假设有一个 Person 类如下所示:

public class Person {
    private int id;
    private String discriminator;
    // some other fields plus getters/setters
}

现在我有一个< code>Person元素的< code>Stream,该流可能包含多个< code>Person实例,这些实例具有相同的< code>id,但具有不同的< code>discriminator值,即< code>[Person{"id": 1," discriminator": "A"},Person{"id": 1," discriminator": "B"},Person{"id": 2," discriminator": "A"},...]

我想做的是,如果至少有一个具有某个id的Person实例具有特定的鉴别器值,则过滤掉具有该id的所有Person。因此,继续上面的示例,按鉴别器值“A”过滤将生成空集合(当然,在缩减操作之后),按鉴别符值“B”过滤将产生不包含任何id等于1的Person实例的集合。

我知道我可以使用groupingBy收集器和分组元素来减少流,Person.id 然后如果映射的列表包含具有指定鉴别器值的Person元素,则从生成的Map中删除映射,但我仍然想知道是否有更简单的方法来实现相同的结果?

共有3个答案

麻茂材
2023-03-14

下面我将介绍我提出的解决方案。首先,我按人员对输入人员集合/流进行分组。id属性,然后我对映射条目进行流式处理,并过滤掉至少有一个值与给定鉴别器匹配的条目。

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class Main {

    public static void main(String[] args) {
        List<Person> persons = Arrays.asList(
            new Person(1, "A"),
            new Person(1, "B"),
            new Person(1, "C"),
            new Person(2, "B"),
            new Person(2, "C"),
            new Person(3, "A"),
            new Person(3, "C"),
            new Person(4, "B")
        );

        System.out.println(persons);
        System.out.println(filterByDiscriminator(persons, "A"));
        System.out.println(filterByDiscriminator(persons, "B"));
        System.out.println(filterByDiscriminator(persons, "C"));
    }

    private static List<Person> filterByDiscriminator(List<Person> input, String discriminator) {
        return input.stream()
            .collect(Collectors.groupingBy(Person::getId))
            .entrySet().stream()
            .filter(entry -> entry.getValue().stream().noneMatch(person -> person.getDiscriminator().equals(discriminator)))
            .flatMap(entry -> entry.getValue().stream())
            .collect(Collectors.toList());
    }

}

class Person {

    private final Integer id;
    private final String discriminator;

    public Person(Integer id, String discriminator) {
        Objects.requireNonNull(id);
        Objects.requireNonNull(discriminator);
        this.id = id;
        this.discriminator = discriminator;
    }

    public Integer getId() {
        return id;
    }

    public String getDiscriminator() {
        return discriminator;
    }

    @Override
    public String toString() {
        return String.format("%s{\"id\": %d, \"discriminator\": \"%s\"}", getClass().getSimpleName(), id, discriminator);
    }
}
李勇
2023-03-14

尤金的答案很好,但我个人更喜欢单一的语句。所以我把他的代码放在一起,放入一个操作中。看起来像这样:

final List<Person> result = persons.stream()
    .filter(p -> "B".equalsIgnoreCase(p.getDiscriminator()))
    .map(Person::getId)
    .collect(
        () -> new ArrayList<>(persons),
        ( list, id ) -> list.removeIf(p -> p.getId() == id),
        ( a, b ) -> {throw new UnsupportedOperationException();}
    );

可能需要提到需要的副本,否则Stream将损坏并遇到null值。

旁注:此版本在尝试并行使用时,当前会引发不受支持的操作异常

吉鸿宝
2023-03-14

如果我正确地理解了您的问题,您将首先找到与鉴别器匹配的所有ID

Set<Integer> ids = persons.stream()
       .filter(p -> "A".equalsIgnoreCase(p.getDiscriminator()))
       .map(Person::getId)
       .collect(Collectors.toSet())

然后删除与以下内容匹配的条目:

persons.removeIf(x -> ids.contains(x.getId()))
 类似资料:
  • 我正在寻找一种方法来声明“2个依赖项之间的依赖项”。 例如,在我的模块中,我ivy.xml以下行: 我的问题是,日志经典 1.0.13 依赖于 slf4j-api 1.7.5,而我的模块依赖于 1.6.6(slf4japiversion 的值)。 我无法更改 slf4japiversion,但将来它可以由其他人升级。 有没有办法声明对logback的依赖关系,以检索与我的slf4j api版本兼容

  • 我有一个对象的集合,每个对象都有一个元素的集合,例如: 如何使用Java 8函数式编程来过滤和收集类型等于“a”的集合? 我尝试了以下方法: 但我得到以下错误: 变量'filteredChildren'初始值设定项'parents。stream()。forEach(p- 如何按类型筛选嵌套集合并收集它们?

  • 问题内容: 我有计算纯python中相邻元素之间差异的算法: 有什么办法可以用Numpy重写此功能? 问题答案: 有方法: 退货

  • 问题内容: 我有以下pandas数据框Top15:在此处输入图片说明 我创建了一个估计每人可引用文件数量的列: 我想知道人均引用文件数量与人均能源供应之间的相关性。因此,我使用该.corr()方法 (皮尔逊相关性): 问题答案: 没有实际数据,很难回答这个问题,但是我想您正在 寻找这样的东西: That calculates the correlation between your two col

  • 我正在使用两个具有扁平数据结构的存储库,例如“MenuItemRepo”和“IngredEnterpo”。它们之间的关系结构是:一个菜单项可以包含许多成分,而一种成分(例如奶酪)可以是许多菜单项的一部分。数据库表的建模如下: > MenuItem表条目 字符串Menuitem-id 字符串名称... MenuItem成分参考表条目 字符串Menuitem-id 字符串成分ID 成分表条目 字符串成

  • 我正在使用Jackson的JsonNode解析json。我的json结构如下所示(设为变量rawJson): 在Java中: 如何通过过滤属性<code>name</code>来获得特定的JsonNode元素?如果我想得到<code>值</code>大于X的JsonNode元素,怎么样?我是否可以在不遍历<code>结果</code>变量的情况下完成这些操作?