如何过滤for中的列表?

时间:2017-08-06 19:14:56

标签: java list filter java-8

我最近遇到了这个问题。 这是我的代码

for(int i=1; i<=repeticiones;i++){
    posiblesComunes.removeIf(p->!periodos.get(i).contains(p));
}

periodos是List(Set(String)),posiblesComunes是Set(String)

我需要做的是只获取句点中所有Set(String)中的字符串。 我尝试使用for来做到这一点,但我收到了下一条消息:

  

我在封闭范围内定义的局部变量必须是最终的或有效的最终

有没有办法解决这个问题?或者另一种获取这些元素的方法? 谢谢!

编辑: 只是一个例子

periodos = {("1-1-16","6-12-16"),("1-1-16","2-8-15"),("3-7-08","1-1-16")}

我需要得到的是&#34; 1-1-16&#34;,这是共同点。

EDIT2:

periodosComunes的示例(for for循环):

periodosComunes = ("1-1-16","6-2-16")

4 个答案:

答案 0 :(得分:3)

您无法从lambda表达式访问本地变量i,因为它在循环期间被修改。最简单的解决方法是在另一个不可变变量中捕获i的当前值:

for(int i=1; i<=repeticiones;i++) {
    int finalI = i;
    posiblesComunes.removeIf(p -> !periodos.get(finalI).contains(p));
}

请注意,for-each循环的变量没有此问题:

for(Set<String> set: periodos.subList(1, repeticiones))
    posiblesComunes.removeIf(p -> !set.contains(p));

但最后,您在这里过度使用Java 8功能。自Java 2以来,可以使用原始集合API完成此操作:

for(Set<String> set: periodos.subList(1, repeticiones))
    posiblesComunes.retainAll(set);

也适用于原始循环:

for(int i=1; i<=repeticiones; i++)
    posiblesComunes.retainAll(periodos.get(i));

在这里,您还可以添加一个快捷方式,因为该组永远不会增长,所以如果没有共同的元素,您可以在该组变空时停止

for(int i=1; i<=repeticiones && !posiblesComunes.isEmpty(); i++)
    posiblesComunes.retainAll(periodos.get(i));

答案 1 :(得分:2)

这个怎么样:

1

我使用Java 9中的集合文字为我节省了一些打字,但这与解决方案无关。

答案 2 :(得分:1)

并非所有列表都为迭代器提供了删除其项目的能力;但是,如果您选择了正确类型的列表,则会将其内置到Iterator界面中。

Iterator i = list.iterator();
while (i.hasNext()) {
    if (i.next().equals(bad)) {
        i.remove();
    }
}

解决方案的简单性足以让您考虑跳过基于流的方法,并且与某些类型的修改不同,Iterator删除不会抛出ConcurrentModificationException

答案 3 :(得分:0)

这应该有效(如果我理解你的需要):

import java.util.stream.*;
import java.util.*;
public class P {

  public static void main(String []a) {
    // Init.
    Set<String> periodosComunes = new HashSet<>(); periodosComunes.add("1-1-16"); periodosComunes.add("6-2-16");
    Set<String> s1 = new HashSet<>(); s1.add("1-1-16"); s1.add("6-12-16");
    Set<String> s2 = new HashSet<>(); s2.add("1-1-16"); s2.add("2-8-15");
    Set<String> s3 = new HashSet<>(); s3.add("1-1-16"); s3.add("3-7-08");
    List<Set<String>> periodos = new ArrayList<>(); periodos.add(s1); periodos.add(s2); periodos.add(s3);

    // Computes the set of commons...
    Set<String> r =  periodosComunes.stream().filter(p->periodos.stream().allMatch(s->s.contains(p))).collect(Collectors.toSet());
    System.out.println(r);                                                   
  }
}

最初位于periodosCommunes的常见句点集合位于r。现在,您可以根据需要使用该集合删除原始集合中的适当集合:

periodosComunes.removeIf(s->!r.contains(s));