фильтровать и устанавливать () в одном потоке - PullRequest
0 голосов
/ 06 февраля 2019

Итак, у меня есть пример кода, с которым я играю, чтобы попытаться выяснить эту логику ниже.Это всего лишь один большой основной метод и два 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 s, которые не совпадают на carId.Моя следующая цель - затем set id (не carId) на соответствующем объекте.

В принципе, если obj1.carId == obj2.carId ТО set obj1.id = obj2.id.

Моя проблема в том, что я не знаю, как это сделать в том же потоке.Является ли это возможным?Я не могу помочь, но думаю, что на этом этапе нужен итератор?

Ответы [ 4 ]

0 голосов
/ 06 февраля 2019

Я бы предложил сначала создать Map отображение carId на 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, вы можете установить идентификатор в peek а затем collect.Это все равно изменит исходные экземпляры, хотя:

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)]
0 голосов
/ 06 февраля 2019

Не выполняйте эти две операции в одном потоке.Это действительно плохой стиль.

Сначала соберите данные.Затем измените элементы.Что-то вроде:

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)));

В противном случае вы можете просто использовать вложенные циклы for-each.

0 голосов
/ 06 февраля 2019

Если для вас работает решение 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);
        }
    }
}

m и nсоответствующие размеры списков.

0 голосов
/ 06 февраля 2019

Вы можете сделать это в Предикате 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());
                }
           };
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...