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

Java流过滤——使用谓词而不是谓词,直接对类的字段进行操作

郎磊
2023-03-14

使用java stream,我有一个ClassA列表,应用于流以进行过滤,所以使用List。stream()。过滤器(谓词)。这样,谓词就需要ClassA的谓词来应用,但我真的想要String的谓词,因为ClassA。Field1是字符串类型。因此,与其让谓词包含f-

缺少的链接是什么,我需要如何转换流才能做到这一点?

对于其他上下文,在过滤之后,我需要从过滤列表中提取第二个字段,因此目标是拥有ClassA。第二场。val(例如,假设我需要提取一个与该项目名称关联的项目ID,所以我按名称过滤)

另外:这是一个简化,实际需要的是使用startswith,而不是equals。

共有3个答案

单于季
2023-03-14

您需要将从类中提取字符串和过滤这些字符串的逻辑分开:

public class StringFieldPredicate<T> implements Predicate<T> {
    
    private final Function<T, String> extractStringFunction;
    private final Predicate<String> stringPredicate;

    public StringFieldPredicate(Function<T, String> extractStringFunction, Predicate<String> stringPredicate) {
        this.extractStringFunction = extractStringFunction;
        this.stringPredicate = stringPredicate;
    }

    @Override
    public boolean test(T t) {
        return stringPredicate.test(extractStringFunction.apply(t));
    }
    
}

它可以这样使用:

public static void main(String[] args) {
    List<Number> numbers = Arrays.asList(1,2,3,4,5);
    numbers.stream().filter(new StringFieldPredicate<>(Number::toString, it -> it.startsWith("1")));
}
葛俊
2023-03-14

受@bedrin帖子的启发,这里提供了一种不需要新课程的方法

假设你有这样的课程:

class ClassA {
    String name;
    //getter, setter ..
}

class ClassB {
    String name;
    //getter, setter ..
}

和列表,例如:

List<ClassA> myAs = List.of(new ClassA("myA_1"), new ClassA("myA_1"), new ClassA("myA_42"));
List<ClassB> myBs = List.of(new ClassB("myB_1"), new ClassB("myB_9"), new ClassB("myB_33"));

然后,您可以编写一个方法,该方法接受字段提取器函数和要测试的字符串:

private static <T> Predicate<T> nameEquals( Function<? super T, ?> fieldExtractor, String toTestAgainst ) {
    return t -> toTestAgainst.equals(fieldExtractor.apply(t));
}

并使用上述方法筛选列表。用法示例:

myAs.stream().filter(nameEquals(ClassA::getName, "myA_1")).forEach(System.out::println);
myBs.stream().filter(nameEquals(ClassB::getName, "myB_1")).forEach(System.out::println);
松阳泽
2023-03-14

映射流本身的建议通常会导致丢失所需的实际类。相反,请应用一个精简的转换包装:

listOfA.stream()
  .filter(a -> sharedPredicate.test(a.getField1()))
  ...
 类似资料:
  • 问题内容: 是否存在Java 8流操作来限制(可能是无限的)直到第一个元素与谓词不匹配? 在Java 9中,我们可以使用下面的示例来打印所有小于10的数字。 由于Java 8中没有这样的操作,以一般方式实现它的最佳方法是什么? 问题答案: 操作并已添加到JDK9。你的示例代码 在JDK 9下编译和运行时,其行为将完全符合你的预期。 JDK 9已发布。可在此处下载:http : //jdk.java

  • 问题内容: 是否存在Java 8流操作来限制(可能是无限的)Stream直到第一个元素与谓词不匹配? 在Java 9中,我们可以takeWhile像下面的示例那样使用它来打印所有小于10的数字。 由于Java 8中没有这样的操作,以一般方式实现它的最佳方法是什么? 问题答案: 这样的操作在Java 8中应该是可能的,但不一定能有效地完成-例如,您不必并行化这样的操作,因为您必须按顺序查看元素。 该

  • 问题内容: 我想做类似的事情: Python的标准库中是否有类似行为? 我知道在这里自己动手很容易,但是我正在寻找一种更标准的方法。 问题答案: 您可以使用filter方法: 或列表理解: 要查找单个元素,可以尝试: 尽管如果没有匹配项将引发异常,因此您可能希望将其包装在try / catch中。方括号()使之成为生成器表达式,而不是列表理解。 就我个人而言,尽管我只是使用常规的过滤器/理解并采用

  • 有两个具有相同结构的地图,即map1和map2,其结构为

  • 问题内容: 我无法编译它,甚至可以链接谓词lambda吗? 或唯一的方法是显式创建一个谓词,然后像这样组合: 还是有更多的“功能优雅”的方式来实现同一目标? 问题答案: 您 可以 使用: 但这不是很优雅。如果要直接指定条件,则只需使用一个λ: