【问题标题】:Iterate two lists simultaneously and create another using streams同时迭代两个列表并使用流创建另一个
【发布时间】:2018-01-04 16:20:19
【问题描述】:

我想使用流实现以下目标:

List<MyObject> list1 = Arrays.asList(obj1, obj2, obj3);
List<Boolean> list2 = Arrays.asList(true, false, true);
List<MyObject> list = new ArrayList<>();
for(int i=0; i<list1.size();i++) {
     if(list2.get(i))
         list.add(list1.get(i));
}

有人可以帮忙吗?这应该很容易,但我是 java 流的新手。

注意: list1 和 list2 的长度总是相同的。

【问题讨论】:

  • 这种方法有什么问题?
  • 如果可能的话,你能不能形成一个List&lt;Entity&gt;List&lt;Pair&lt;YourObject, Boolean&gt;&gt; 而不是创建两个独立的列表?另外,我不明白你为什么需要在这里使用流
  • @AndrewTobilko 那会怎样(单列)?
  • @ParagJ,例如对的列表 - 每对都有一个 MyObject 和一个对应的 Boolean 值 (ob1=true,obj2=false)

标签: java lambda java-stream


【解决方案1】:

你可以这样做:

List<MyObject> list = IntStream.range(0, list1.size())
    .filter(i->list2.get(i))
    .map(i->list1.get(i))
    .collect(Collectors.toList())

如果 Java 有内置的 zip 流可能会更好。例如,您可以使用 Guava:

 Streams.zip(list2.stream(), list1.stream(), (a,b) -> a ? b : null)
    .filter(Objects::nonNull)
    .collect(Collectors.toList())

【讨论】:

  • 由于您以IntStream 开头,因此您需要mapToObj。但是你可以简化为.filter(list2::get) .mapToObj(list1::get)...
  • 我猜最终列表会保留 list1 的插入顺序?
  • @FedericoPeraltaSchaffner:无论List类型Collectors.toList()会返回,它总是反映流的遇到顺序,即list1/list2的顺序(实际上是IntStream.range 的升序用作列表索引)。
  • @Holger 你是对的。收集时为顺序流保留遇到顺序,Collectors.toList() 预计会返回一个反映此顺序的列表(无论实现方式)。你知道这是否在文档中明确说明?我的意思是,我们可以放心地假设订单会得到尊重,因为我们在这里讨论的是列表,但如果它在文档中......
  • @FedericoPeraltaSchaffner:在这种情况下,情况正好相反。所有无序收集器在其文档中都有关于无序的明确声明。由于这也是通过characteristics 报告的,因此如果UNORDERED 不存在,并行流必须以在遇到顺序中产生结果的方式使用组合器。这是有保证的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-20
  • 2012-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多