有 Java 编程相关的问题?

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

一个流中的java筛选器和set()

所以我有一些我正在玩的示例代码,试图找出下面的逻辑。它只是一个大型main方法和两个pojo,但它会运行。我正在调试以在终止点获取值

public class Main {

    public static void main(String[] args) {

        obj1 obj1 = new obj1();
        obj1 obj12 = new obj1();

        obj2 obj2 = new obj2();
        obj2 obj22 = new obj2();

        obj1.id = 123L;
        obj1.carId = 1234L;
        obj12.id = 123L;
        obj12.carId = 1234L;

        obj2.carId = 1234L;
        obj22.carId = 12345L;

        ArrayList<obj1> obj1Arr = new ArrayList<>();
        ArrayList<obj2> obj2Arr = new ArrayList<>();

        obj1Arr.add(obj1);
        obj1Arr.add(obj12);

        obj2Arr.add(obj2);
        obj2Arr.add(obj22);

        List<obj2> newCarList= obj2Arr.stream()
                .filter(anObjOf2 -> obj1Arr
                        .stream()
                        .anyMatch(carReg -> carReg.getCarId().equals(anObjOf2.getCarId())))
                .collect(Collectors.toList());
    }
}

POJO1:

public class obj1 {

    Long id = null;
    Long carId = null;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getCarId() {
        return carId;
    }

    public void setCarId(Long carId) {
        this.carId = carId;
    }
}

POJO2:

public class obj2 {

    Long id = null;
    Long carId = null;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getCarId() {
        return carId;
    }

    public void setCarId(Long carId) {
        this.carId = carId;
    }
}

如您所见,我正在流式处理并过滤掉任何与obj不匹配的carId。我的下一个目标是在匹配的对象上set{}(而不是carId)

基本上,如果obj1.carId == obj2.carId,那么set obj1.id = obj2.id

我的问题是,我不知道如何在同一个流中执行此操作。可能吗?我忍不住认为现在需要一个迭代器


共 (4) 个答案

  1. # 1 楼答案

    如果一个O(m*n)解决方案适合您,那么更简单的实现就是使用for循环,如下所示:

    // classes renamed for naming convention and relatiing to question at the same time 
    List<ObjectTwo> newCarList = new ArrayList<>();
    for(ObjectTwo objectTwo: objectTwoArr) {
        for (ObjectOne objectOne : objectOneArr) {
            if (objectTwo.getCarId().equals(objectOne.getCarId())) {
                objectOne.setId(objectTwo.getId());
                newCarList.add(objectTwo);
            }
        }
    }
    

    mn分别是列表的大小

  2. # 2 楼答案

    我建议首先为第一个列表中的每个元素创建一个Map映射carIdid(我对类进行了一些修改,使其更具可读性,并删除了重复的ID,我认为这是一个错误):

    @Data @AllArgsConstructor
    class Car {
        Long id = null;
        Long carId = null;
    }
    List<Car> obj1Arr = Arrays.asList(new Car(1L, 123L), new Car(2L, 1234L));
    List<Car> obj2Arr = Arrays.asList(new Car(0L, 1234L), new Car(0L, 12345L));
    
    Map<Long, Long> carIdToId = obj1Arr.stream()
            .collect(Collectors.toMap(Car::getCarId, Car::getId));
    // [Car(id=2, carId=1234), Car(id=0, carId=12345)]
    

    然后,您可以使用此Map来筛选具有相同carID的车辆,而无需相互比较。然后,使用forEach只需在原始列表中设置Id即可

    obj2Arr.stream()
            .filter(anObjOf2 -> carIdToId.containsKey(anObjOf2.getCarId()))
            .forEach(anObjOf2 -> anObjOf2.setId(carIdToId.get(anObjOf2.getCarId())));
    System.out.println(obj2Arr);
    // [Car(id=2, carId=1234), Car(id=0, carId=12345)]
    

    如果希望具有相等carId的项,可以在peekcollect中设置ID。这仍将修改原始实例,但:

    obj2Arr = obj2Arr.stream()
            .filter(anObjOf2 -> carIdToId.containsKey(anObjOf2.getCarId()))
            .peek(anObjOf2 -> anObjOf2.setId(carIdToId.get(anObjOf2.getCarId())))
            .collect(Collectors.toList());
    System.out.println(obj2Arr);
    // [Car(id=2, carId=1234)]
    

    或者创建一个全新实例的列表:

    obj2Arr = obj2Arr.stream()
            .map(Car::getCarId)
            .filter(carIdToId::containsKey)
            .map(carId -> new Car(carIdToId.get(carId), carId))
            .collect(Collectors.toList());
    System.out.println(obj2Arr);
    // [Car(id=2, carId=1234)]
    
  3. # 3 楼答案

    不要在一个流中执行这两个操作。这是一种非常糟糕的风格

    首先收集数据。然后对元素进行变异。比如:

    Map<obj2, Optional<obj1>> map = 
        obj2Arr.stream()
               .collect(toMap(identity(), o2 -> obj1Arr.stream()
                                                      .filter(o1 -> o1.getCarId().equals(o2.getCarId()))
                                                      .findAny()));
    
    map.forEach((o1, optO2) -> optO2.ifPresent(o2 -> o1.setId(o2.id)));
    

    否则,可以对每个循环使用嵌套

  4. # 4 楼答案

    您可以在谓词anyMatch中执行此操作

    List<obj2> newCarList= obj2Arr.stream()
                .filter(anObjOf2 -> obj1Arr
                        .stream()
                        .anyMatch(carReg ->  {
                if(carReg.getCarId().equals(anObjOf2.getCarId()))) {
                     carReg.setId(anObjOf2.getId());
                      return true;
                   }
               return false;
         }).collect(Collectors.toList());
    

    第二种方法

    先过滤

    List<obj2> newCarList= obj2Arr.stream()
                .filter(anObjOf2 -> obj1Arr
                        .stream()
                        .anyMatch(carReg -> carReg.getCarId().equals(anObjOf2.getCarId())))
                .collect(Collectors.toList());
    

    现在设置id

    newCarList.forEach(obj->{
               obj1Arr.forEach(o-> {
                if(o.getCarId().equals(obj.getCarId()) {
                      o.setId(obj.getId());
                    }
               };
        });