有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用流删除一个列表中的元素(如果存在于另一个列表中)

我在这里找不到关于这个问题的线索。如果一个列表(cars1)中的元素存在于另一个列表(cars2)中,我试图使用java流删除其中的元素(在我的例子中是Cars)。 我试着使用removeIf,但后来觉得它更适合处理字符串列表等

    Car c1 = new Car();
    c1.id = 1;
    c1.name = "C1";

    Car c2 = new Car();
    c2.id = 2;
    c2.name = "C2";

    List<Car> cars1 = new ArrayList<Car>();
    cars1.add(c1);
    cars1.add(c2);

    List<Car> cars2 = new ArrayList<Car>();
    cars2.add(c2);

    // TODO : Remove all the cars from cars1 list that are in cars2 list using java streams

共 (2) 个答案

  1. # 1 楼答案

    只需使用removeAll()方法即可完成。必须在Car类中实现hashcode和equals。 然后你可以cars1.removeAll(cars2);。此声明只会在cars1列表中留下c1

  2. # 2 楼答案

    如果方法hashCodeequals在类Car中正确实现,则基于流的解决方案可能如下所示:

    • 过滤掉这些值,收集到一个新列表中
    // Predicate.not added in Java 11
    List<Car> notJava11 = cars1.stream()
                            .filter(Predicate.not(cars2::contains))
                            .collect(Collectors.toList());
    
    List<Car> notIn2 = cars1.stream()
                            .filter(car -> !cars2.contains(car))
                            .collect(Collectors.toList());
    
    
    • forEach表示cars2(影响cars1):
    cars2.forEach(cars1::remove); 
    // no need to call cars2.stream().forEach(cars1::remove);
    

    这里,第一个出现的Car实例在cars1中被删除

    • removeIf也应该有效
    cars1.removeIf(cars2::contains);
    

    如果由于某种原因equals/hashCode未在类Car中重写,则可能会提供以下解决方案:

    List<Car> notIn2 = cars1
            .stream()
            .filter(c1 -> cars2
                .stream()
                .noneMatch(c2 -> 
                     c1.getId() == c2.getId()
                     && Objects.equals(c1.getName(), c2.getName())
                )
            )
            .collect(Collectors.toList());
    
    • removeIf
    cars1.removeIf(c1 -> cars2
        .stream()
        .anyMatch(c2 -> c1.getId() == c2.getId() 
            && Objects.equals(c1.getName(), c2.getName())
        )
    );