java 用流输出一对对象

shstlldc  于 2023-01-16  发布在  Java
关注(0)|答案(5)|浏览(194)

我有两个类FooBar,其中Foo在其属性中有一个Bar的列表,如下所示:

public class Bar {
   int id;
   ...

   public boolean isGood() {...}
}
public class Foo {
   int id;
   List<Bar> bars;
   ...
    public boolean hasBadBar() {
        boolean hasOnlyGoodBars = bars.stream().allMatch(Bar::isGood);
        return !hasOnlyGoodBars;
    }
}

现在,假设我有一个名为foosFoo列表,并希望遍历foos并报告包含错误BarFoobar.isGood()为false)。我想报告(字符串版本的Foo id,字符串版本的Bar id)这样的事件。有什么想法如何做符合stream()
我可以单独报告id的这样的Foos(或这样的酒吧),但我不知道如何做一对。

62lalag4

62lalag41#

这应该可以达到目的:

List<Pair<Foo,Bar>> pairs = foos.stream().
            flatMap(
                    //take all the non-good Bars and create a Pair together with its Foo
                    foo -> foo.bars.stream().
                           filter(Predicate.not(Bar::isGood)).
                           map(bar -> new Pair(foo, bar))
            ).
            collect(Collectors.toList());

其中Pair是某个
编辑:要获得保存他们的idList<Pair<String,String>>

  • 要么使用评论中的Holger方法:

new Pair<>(String.valueOf(foo.id), String.valueOf(bar.id))

  • 或者,如果您需要这个列表和id对的列表,请将现有的List<Pair<Foo,Bar>> pairs转换为:
List<Pair<String,String>> idPairs = pairs.stream()
   .map(p -> new Pair<>(String.valueOf(p.getLeft().id),
                       String.valueOf(p.getRight().id)))
   .collect(Collectors.toList());
zbdgwd5y

zbdgwd5y2#

由于需要返回列表的列表,因此可能需要使用flatMap来收集所有内容

List<Pair> fooBarPair = foos.stream().flatMap( foo -> {
            List<Bar> badBars = foo.getBadBars();
            return badBars.stream().map( bar -> new Pair( foo.toString(), bar.toString() ) );
        } ).toList();
public class Test {
    @AllArgsConstructor
    @ToString(exclude = "isGood")
    static class Bar {
        int id;
        boolean isGood;

        public boolean isGood() {return isGood;}
        public boolean isBad() {return !isGood;}
    }

    @AllArgsConstructor
    @ToString(exclude = "bars")
    @Getter
    public class Foo {
        int id;
        List<Bar> bars;
        public boolean hasBadBar() {
            return bars.stream().filter(Bar::isBad).toList().size() != bars.size();
        }
        public List<Bar> getBadBars() {
            return bars.stream().filter( Bar::isBad ).collect( Collectors.toList());
        }
    }

    @AllArgsConstructor
    @ToString
    static class Pair {
        String foo;
        String bar;
    }

    @org.junit.jupiter.api.Test
    void test() {
        List<Foo> foos = new ArrayList<>();
        List<Bar> barsFoo0 = new ArrayList<>();
        barsFoo0.add( new Bar( 1, true ) );
        barsFoo0.add( new Bar( 2, true ) );
        barsFoo0.add( new Bar( 3, false ) );

        List<Bar> barsFoo1 = new ArrayList<>();
        barsFoo1.add( new Bar( 1, false ) );
        barsFoo1.add( new Bar( 2, false ) );
        barsFoo1.add( new Bar( 3, true ) );

        foos.add( new Foo( 0, barsFoo0 ) );
        foos.add( new Foo( 1, barsFoo1 ) );

        List<Pair> fooBarPair = foos.stream().flatMap( foo -> {
            List<Bar> badBars = foo.getBadBars();
            return badBars.stream().map( bar -> new Pair( foo.toString(), bar.toString() ) );
        } ).toList();

        System.out.println(fooBarPair);

    }


}
ghhaqwfi

ghhaqwfi3#

假设1)你只关心第一个坏条,2)你在Foo中添加了一个可选的firstBadBar()方法,这段代码可以把id收集到一个map中:

Map<String,String> result = foos.stream()
        .filter( foo -> foo.firstBadBar().isPresent() )
        .collect( Collectors.toMap( foo -> String.valueOf( foo.id ), foo -> String.valueOf( foo.firstBadBar().get().id ) ) );
jdg4fx2g

jdg4fx2g4#

如果不需要收集,则应执行以下操作:

foos.stream()
        .filter(f ->f.hasBadBars())
        .forEach(f -> {
            System.out.printf("Foo %d has bad bars:%n", f.getId());
            f.getBars().stream()
                .filter(b -> !b.getIsGood())
                .forEach(bad ->System.out.printf("\tId of bad Bar: %d%n", bad.getId()));
        });
ljsrvy3e

ljsrvy3e5#

您可以创建Map<Foo, List<Bar>>(将FooMap到包含与Foo关联的所有坏BarList<Bar>)。
首先,您有一个List<Foo> foos
然后,您可以使用stream()

Map<Foo, List<Bar>> result = foos.stream()
    .filter(x -> x.hasBadBar())
    .map(x -> {
         List<Bar> badBars = new ArrayList<>(x.bars);
         badBars.removeIf(bar -> bar.isGood());
         return new Pair<>(x, badBars);
    })
    .collect(Collectors.toMap(Pair::getKey, Pair::getValue));

filter方法仅用于保留具有坏的BarFoo对象,然后使用map方法为每个Foo对象创建Pair<Foo, List<Bar>>对象,以原始Foo对象为键,以坏的Bar的列表为值。collect方法用于将流的元素收集到Map中。
然后,您可以使用Map打印Foo和所有对应的坏Bar

相关问题