Java流-获取连续相同字段的对象
我不知道如何用一个好的标题来描述我想要达到的目标。我有一个对象列表,每个对象都有一个布尔成员。我想过滤这个列表,以便在最后从列表中获取第一个对象,所有这些对象的布尔成员都设置为true 这就是我在没有streams的情况下应该做的,将每个对象添加到一个新的列表中,getter方法为其返回true,并在第一个元素返回false时停止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()){
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 passedfilter(..)
,那么您的代码将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;
}
}