Как удалить дубликаты объектов из списка на основе определенного поля, но добавить количество перед удалением? - PullRequest
1 голос
/ 25 сентября 2019

У меня есть класс сборки, имеющий несколько полей.

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

package com.company;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<Assembly> assemblies = new ArrayList<>();

        assemblies.add(new Assembly("abc1", 3.0));
        assemblies.add(new Assembly("abc2", 6.0));
        assemblies.add(new Assembly("abc3", 8.4));
        assemblies.add(new Assembly("abc4", 9.0));
        assemblies.add(new Assembly("abc1", 4.2));
        assemblies.add(new Assembly("abc1", 6.3));

        System.out.println("List with duplicates: "+assemblies);

        HashSet<String> assmCode=new HashSet<>();
        assemblies.removeIf(e->!assmCode.add(e.getAssemblyCode())); //remove the last two abc1

        //but i need to add 4.2, 6.3 to 3.0 before removing
        System.out.println("List without duplicates: "+assemblies);
    }
}

class Assembly{
    private String assemblyCode;
    private double assemblyQty;
    //There will be more such fields

    public Assembly(String assemblyCode, double assemblyQty) {
        this.assemblyCode = assemblyCode;
        this.assemblyQty = assemblyQty;
    }

    public String getAssemblyCode() {
        return assemblyCode;
    }

    public void setAssemblyCode(String assemblyCode) {
        this.assemblyCode = assemblyCode;
    }

    public double getAssemblyQty() {
        return assemblyQty;
    }

    public void setAssemblyQty(double assemblyQty) {
        this.assemblyQty = assemblyQty;
    }

    @Override
    public String toString() {
        return "Assembly{" +
                "assemblyCode='" + assemblyCode + '\'' +
                ", assemblyQty=" + assemblyQty +
                '}';
    }
}

Пожалуйста, дайте мне знать, могу ли я выполнить такую ​​операцию, прежде чем удалять дубликаты объектов.Я новичок в API Java коллекции, поэтому извините за вопрос, если решение легко.

Просто чтобы уточнить, вывод должен быть следующим:

Список с дубликатами: [Assembly {assemblyCode = 'abc1', assemblyQty = 3.0}, Assembly {assemblyCode = 'abc2', assemblyQty = 6.0}, Assembly {assemblyCode = 'abc3', assemblyQty = 8.4}, Assembly {assemblyCode = 'abc4', assemblyQty = 9.0},Assembly {assemblyCode = 'abc1', assemblyQty = 4.2}, Assembly {assemblyCode = 'abc1', assemblyQty = 6.3}]

Список без дубликатов: [Assembly {assemblyCode = 'abc1', assemblyQty = 13.5},Assembly {AssemblyCode = 'abc2', AssemblyQty = 6.0}, Assembly {AssemblyCode = 'abc3', AssemblyQty = 8.4}, Assembly {AssemblyCode = 'abc4', AssemblyQty = 9.0}]

1 Ответ

0 голосов
/ 25 сентября 2019

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

Вам необходимо сохранить дубликаты значений, чтобы иметь возможность их повторного использования.
removeIf() не будет собирать эту информацию.

Вы можете использовать итератор для удаления элементов и ввести переменную Map для хранения дублирующейся информации:

Map<String, Double> assemblyDupMap = new HashMap<>();
for (Iterator<Assembly> it = assemblies.iterator(); it.hasNext(); ){
      Assembly a = it.next();
      if(!assmCode.add(a.getAssemblyCode())){ 
         // store the duplicate information 
         double currentQty = assemblyDupMap.getOrDefault(a.getAssemblyCode(), 0D);
         assemblyDupMap.put(a.getAssemblyCode(), currentQty + a.getAssemblyQty()); 
         // remove it from the list
         it.remove();        
      }

};

Затем обновите количество:

assemblies.forEach( a -> Optional.ofNullable(assemblyDupMap.get(a.getAssemblyCode()))
                                 .ifPresent(qty -> a.incrementQty(qty))
                  );

По мере того как выможно заметить, это достаточно многословно.По сути, потому что нам нужно обновить элементы списка.
Если приемлемо создание нового списка вместо использования существующего, потоковый подход является более сжатым.

Группируйте объекты по их ассемблерному коду на карте, суммируйте их количество по коду и сохраняйте только объекты в качестве результата:

new ArrayList<>(assemblies.stream()
                          .collect(toMap(Assembly::getAssemblyCode, o -> o,
                                         (a, b) -> new Assembly(a.getAssemblyCode(),
                                                                a.getAssemblyQty() + b
                                                                    .getAssemblyQty()),
                                         LinkedHashMap::new)
                          )
                          .values());

Для записи, суммирование double s может дать«нежелательный» результат.BigDecimal может вас заинтересовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...