流:过滤子项,返回父项

Ant*_*oly 5 java java-8 java-stream

假设一个类MyClass:

public class MyClass {

    private final Integer myId;
    private final String myCSVListOfThings;

    public MyClass(Integer myId, String myCSVListOfThings) {
        this.myId = myId;
        this.myCSVListOfThings = myCSVListOfThings;
    }

    // Getters, Setters, etc
}
Run Code Online (Sandbox Code Playgroud)

这个流:

final Stream<MyClass> streamOfObjects = Stream.of(
        new MyClass(1, "thing1;thing2;thing3"),
        new MyClass(2, "thing2;thing3;thing4"),
        new MyClass(3, "thingX;thingY;thingZ"));
Run Code Online (Sandbox Code Playgroud)

我想要返回每个实例MyClass包含一个条目"thing2"myCSVListOfThings.

如果我想要List<String>包含myCSVListOfThings这个可以轻松完成:

List<String> filteredThings = streamOfObjects
        .flatMap(o -> Arrays.stream(o.getMyCSVListOfThings().split(";")))
        .filter("thing2"::equals)
        .collect(Collectors.toList()); 
Run Code Online (Sandbox Code Playgroud)

但我真正需要的是一个List<MyClass>.

这就是我现在所拥有的:

List<MyClass> filteredClasses = streamOfObjects.filter(o -> {
     Stream<String> things = Arrays.stream(o.getMyCSVListOfThings().split(";"));
     return things.anyMatch(s -> s.equals("thing2"));
}).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但不知怎的,它感觉不对.任何更清洁的解决方案比打开一个新的Stream内部Predicate

Ser*_*tin 7

首先,我建议您添加额外的方法MyClass public boolean containsThing(String str),以便您可以像这样转换代码:

List<MyClass> filteredClasses = streamOfObjects
  .filter(o -> o.containsThing("thing2"))
  .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

现在你可以根据需要实现这个方法取决于输入数据:拆分Stream,拆分Set,甚至搜索substring(如果可能和有意义),如果需要,缓存结果.

您对此类的使用了解得更多,因此您可以做出正确的选择.