Java流-获取连续相同字段的对象

Java流-获取连续相同字段的对象,java,java-8,java-stream,Java,Java 8,Java Stream,我不知道如何用一个好的标题来描述我想要达到的目标。我有一个对象列表,每个对象都有一个布尔成员。我想过滤这个列表,以便在最后从列表中获取第一个对象,所有这些对象的布尔成员都设置为true 这就是我在没有streams的情况下应该做的,将每个对象添加到一个新的列表中,getter方法为其返回true,并在第一个元素返回false时停止 int i = 0; while(i < list.size()){ if(!list.get(i).isMemberTrue()){

我不知道如何用一个好的标题来描述我想要达到的目标。我有一个对象列表,每个对象都有一个布尔成员。我想过滤这个列表,以便在最后从列表中获取第一个对象,所有这些对象的布尔成员都设置为true

这就是我在没有streams的情况下应该做的,将每个对象添加到一个新的列表中,getter方法为其返回true,并在第一个元素返回false时停止

int i = 0;
while(i < list.size()){
    if(!list.get(i).isMemberTrue()){
        break;
    }
    else{
        newList.add(list.get(i));
    }
    i++;
}
inti=0;
而(i

对于顺序流,这是否可能?

也许类似的方法可以工作:

ArrayList<YourClass> newList = new ArrayList<>(
    list.stream()
   .filter(obj -> obj.isMemberTrue())
   .collect(Collectors.toList())
);
ArrayList newList=new ArrayList(
list.stream()
.filter(obj->obj.isMemberTrue())
.collect(收集器.toList())
);

如果要将其作为列表返回,请记住导入java.util.stream.Collectors。

您可以使用此代码获取列表

list.subList(0,list.indexOf(list.stream()
                    .filter(member->!member::isMemberTrue)
                    .findFirst()
                    .orElse(list.size()))
或者你可以把它当作

int endIndex=list.indexOf(list.stream()
                    .filter(member->!member::isMemberTrue)
                    .findFirst()
                    .orElse(list.size());
然后

在本例中,我通过使用list::sublist(…)
获得新的列表,然后在条件变为false之前使用
lambda`获取所有成员

经过审查,我更新了答案
希望这有帮助!:)

您可以使用streams实现解决方案。只需记住列表中的前一个

public class ListTest
{

    @Test
    public void test()
    {

        List<Foo> list = new ArrayList<>();
        list.add(new Foo(true));
        list.add(new Foo(true));
        list.add(new Foo(true));
        list.add(new Foo(false));
        list.add(new Foo(false));
        list.add(new Foo(true));
        list.add(new Foo(true));


        List<Foo> firstSequence = list.stream().filter(new Predicate<Foo>() {

            private boolean inFirstSequence = true;

            @Override
            public boolean test(Foo foo)
            {
                // turns into false, if first false value is found
                inFirstSequence = inFirstSequence && foo.b;

                return inFirstSequence;                
            }
        }).collect(Collectors.toList());

        Assert.assertEquals(3, firstSequence.size());
    }

    private class Foo
    {
        public Foo(boolean b)
        {
            super();
            this.b = b;
        }

        boolean b = true;
    }
}
公共类列表测试
{
@试验
公开无效测试()
{
列表=新的ArrayList();
添加(新Foo(true));
添加(新Foo(true));
添加(新Foo(true));
添加(新Foo(false));
添加(新Foo(false));
添加(新Foo(true));
添加(新Foo(true));
List firstSequence=List.stream().filter(新谓词(){
私有布尔inFirstSequence=true;
@凌驾
公共布尔测试(Foo-Foo)
{
//如果找到第一个假值,则变为假
inFirstSequence=inFirstSequence&&foo.b;
返回inFirstSequence;
}
}).collect(Collectors.toList());
Assert.assertEquals(3,firstSequence.size());
}
私家班
{
公共Foo(布尔b)
{
超级();
这个.b=b;
}
布尔b=真;
}
}

list.stream().filter(member->member::isMemberTrue).findFirst()
还有一件事,如果列表中的第一个
成员不是成员,则循环将
中断
,因此请确保正在执行的操作是,如果第一个对象返回false,则结果列表可能为空。从答案中可以看出,您已经发现,通过经典循环切换到流是没有意义的。所有解决方案尝试(到目前为止)要么使用中间对象,要么放弃潜在的并行性,要么多次迭代列表。我的建议是:坚持循环。我想得到它返回true的第一个连续对象,而不是它返回true的每个对象。@semaphor检查注释:)@semaphor我不知道这是否适用于流。只需添加
findFirst()
而不是
collect…
@Asterisk Ninja,但这将只返回第一个返回true的对象,但我希望从开始到第一个返回false的所有对象。您尝试过并行执行代码吗?你得到同样的结果了吗?我想不是。所以请不要在无状态表达式中使用状态,因为可能会发生意外行为。@Flown。谢谢你的评论。如果我把这项财产列入分类测试,我会同意你的意见。因此,状态仅在方法test()的调用堆栈中使用?!?您可以看到一个示例,说明为什么不应该在findFirst()中的
流中使用state,它将为您提供对象,而不是索引。所以您必须实际使用子列表(0,list.indexOf(firstObject)),前提是存在这样的第一个对象。@mtj感谢您指出,我将edit@AsteriskNinja这应该可以完成您的工作:
intlow=IntStream.range(0,list.size()).filter(i->!list.get(i).isMemberTrue()).findFirst().orElse(0)。但是要小心,如果底层实现不是一个
RandomAccess
列表。@flwn what if list passed
filter(..)
,那么您的代码将
0
的结果降低到不需要的程度,您可以使用
orElse(list.size()
)@AsteriskNinja您是对的。它应该是
.orElse(list.size())
public class ListTest
{

    @Test
    public void test()
    {

        List<Foo> list = new ArrayList<>();
        list.add(new Foo(true));
        list.add(new Foo(true));
        list.add(new Foo(true));
        list.add(new Foo(false));
        list.add(new Foo(false));
        list.add(new Foo(true));
        list.add(new Foo(true));


        List<Foo> firstSequence = list.stream().filter(new Predicate<Foo>() {

            private boolean inFirstSequence = true;

            @Override
            public boolean test(Foo foo)
            {
                // turns into false, if first false value is found
                inFirstSequence = inFirstSequence && foo.b;

                return inFirstSequence;                
            }
        }).collect(Collectors.toList());

        Assert.assertEquals(3, firstSequence.size());
    }

    private class Foo
    {
        public Foo(boolean b)
        {
            super();
            this.b = b;
        }

        boolean b = true;
    }
}