Как суммировать объекты с одинаковым именем в ObservableList <> - PullRequest
0 голосов
/ 20 декабря 2018

Я сделал TableView, который заполнен объектами ингредиентов из базы данных.Я хочу проверить, есть ли Ингредиентные Объекты с тем же именем и единицей, и если да, суммируйте их количество с одним Ингредиентным Объектом.

Я попытался использовать 2 вложенных цикла for и проверил условия.Скажем, например, у меня есть 2 идентичных объекта Ingredient в моем ObservableList, и я заполняю свой TableView приведенным ниже кодом, я получаю ингредиенты, как они были раньше, и суммирую их.

Соответствующая часть класса контроллера:

@FXML 
    void loadData(ActionEvent e) throws Exception{
//      System.out.println(menuList.size());
        ObservableList<ObservableList<Ingredients>> result = FXCollections.observableArrayList();
        ObservableList<Ingredients> all = FXCollections.observableArrayList();
        try {
            for(String s : menuList) {
                result.add(DBUtils.getIngredById(DBUtils.getContent(s)));
            }
            for(ObservableList<Ingredients> obs : result) {
                for(Ingredients i : obs) {
                    all.add(i);
                }
            }
            ObservableList<Ingredients> asdad = mergeList(all);
            loadTable(asdad);
        } catch (Exception ex) {
            System.out.println("Error in loadTable()\n");
            throw ex;
        }
    }

private ObservableList<Ingredients> mergeList(ObservableList<Ingredients> all) {
    ObservableList<Ingredients> newList = FXCollections.observableArrayList();
    for(Ingredients i : all) {
        for(Ingredients m : all) {
            if(all.indexOf(i) != all.indexOf(m)) {
                if(i.getIngred().equals(m.getIngred())) {
                    if(i.getUnit().equals(m.getUnit())) {
                        newList.add(sumUpIng(i, m));
                    }
                }
            }else {
                newList.add(m);
            }
        }

    }
    return newList;
}

private Ingredients sumUpIng(Ingredients i, Ingredients s) {
    Ingredients ing = new Ingredients();
    ing.setAmount(i.getAmount() + s.getAmount());
    ing.setUnit(i.getUnit());
    ing.setIngred(i.getIngred());

    return ing;
}

private void loadTable(ObservableList<Ingredients> data) {
    tblShopping.setItems(data);
}

Класс ингредиентов https://pastebin.com/N35LeDf4

public class Ingredients {

    private IntegerProperty id;
    private DoubleProperty amount;
    private StringProperty unit;
    private StringProperty ingred;

    public Ingredients() {
        this.id = new SimpleIntegerProperty();
        this.amount = new SimpleDoubleProperty();
        this.unit = new SimpleStringProperty();
        this.ingred = new SimpleStringProperty();
    }
    //getters and setters
}

1 Ответ

0 голосов
/ 20 декабря 2018

Ваш вложенный цикл не будет работать должным образом.Одна из причин этого заключается в том, что он выполняется для каждой комбинации индексов.Для неравных индексов цикл выполняется дважды.Кроме того, может быть более 2 ингредиентов с одинаковыми комбинациями свойств unit / ingred.Наилучший способ сделать это - сохранить индексы отображения Map из комбинации ключа unit / ingred в значения Integer, содержащие значение, содержащее индекс элемента с этой комбинацией в результате.список.

/**
 * Class implementing hashCode/equals based on ingred and unit
 * for use as key in a HashMap
 */
private static class IngredientWrapper {
    private final Ingredients ingredient;

    private IngredientWrapper(Ingredients ingredient) {
        this.ingredient = ingredient;
    }

    @Override
    public int hashCode() {
        return Objects.hash(ingredient.getIngred(), ingredient.getUnit());
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        IngredientWrapper other = (IngredientWrapper) obj;
        return Objects.equals(ingredient.getIngred(), other.ingredient.getIngred())
                && Objects.equals(ingredient.getUnit(), other.ingredient.getUnit());
    }

}

private static ObservableList<Ingredients> mergeList(ObservableList<Ingredients> all) {
    ObservableList<Ingredients> newList = FXCollections.observableArrayList();
    Map<IngredientWrapper, Integer> indices = new HashMap<>();
    Integer index = 0;

    for(Ingredients ingredient : all) {
        Integer listIndex = indices.putIfAbsent(new IngredientWrapper(ingredient), index);
        if (listIndex == null) {
            // combination not yet in the list
            newList.add(ingredient);
            index++;
        } else {
            // combination already in the list
            Ingredients listIngredient = newList.get(listIndex);
            listIngredient.setAmount(listIngredient.getAmount() + ingredient.getAmount());
        }

    }
    return newList;
}
...