Есть ли лучший способ я могу обрабатывать мой Generi c BaseClass в наследовании классов? - PullRequest
1 голос
/ 15 января 2020

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

Вот мой базовый класс c, который должен быть расширен другими классами:

public class BaseFiller<T> {

private WorkBook workBook;
private List<T> act_Bwa;
private List<T> act_Balance;
private List<T> p_l_v_e_L;


public BaseFiller(WorkBook workBook,
                  List<T> act_Bwa,
                  List<T> act_Balance,
                  List<T> p_l_v_e_L) {
    this.workBook = workBook;
    this.act_Bwa = act_Bwa;
    this.act_Balance = act_Balance;
    this.p_l_v_e_L = p_l_v_e_L;
}


protected static <T> Predicate<T> distinctByProperty(Function<? super T, ?> keyExtractor) {
    Map<Object, Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}



protected static <T> Map<Integer, String> mapListToMap(Collection<? extends T> entityList, Function<? super T, Integer> intProperty,
                                                           Function<? super T, String> stringProperty) {
    return entityList.stream()
            .collect(Collectors.toMap(intProperty, stringProperty));
}


 //Getter & Setter

 }

Следующий класс расширяет базовый класс:

public class FinanceBalanceFiller<T> extends BaseFiller<T> {

.
.
.


public FinanceBalanceFiller(WorkBook workBook, List<T> act_Bwa,
                            List<T> act_Balance,
                            List<T> p_l_v_e_L) {
    super(workBook, act_Bwa, act_Balance, p_l_v_e_L);
}



public Map<Integer, String> makeMapFromAllLists() {
    List<ResultlinevaluesEntity> res = new ArrayList<>();
    for (List<ResultlinevaluesEntity> list : getAct_Bwa()) {
        res.addAll(list);
    }

    //removes all duplicates from List by DbNr
    List<ResultlinevaluesEntity> resWithoutDuplicates = res.stream()
            .filter(distinctByProperty(ResultlinevaluesEntity::getDb_nr))
            .collect(Collectors.toList());

    //creates HashMap (Key = DbNr, Value = name)
    return mapListToHashMap(resWithoutDuplicates, ResultlinevaluesEntity::getDb_nr,
            ResultlinevaluesEntity::getName);
}

В методе makeMapFromAllLists () у меня проблемы в моем For l oop. Это выдает ошибку, что типы не совместимы друг с другом.

Ошибка: (116, 68) java: несовместимые типы: T нельзя преобразовать в java .util.List

Я понимаю, и я изменил это так:

    List<T> res = new ArrayList<>();
    for (List<T> list : getAct_Bwa()) {
        res.addAll(list);
    }

Но это тоже не работает, потому что типы здесь тоже не подходят. Кроме того, у меня возникают проблемы с Methdode differentByProperty из базового класса. Здесь компилятор говорит:

Нестатистический метод c не может быть вызван из статического c контекста

Между тем я полностью сбит с толку и могу дальше не будем.

Итак, моя цель состоит в том, чтобы все методы в методе makeMapFromAllLists () обслуживали не только ListType "ResultLineValuesEntity", но и другие типы.

Может ли кто-нибудь помочь мне и показать мне, как обращаться с дженериками на этом этапе?

1 Ответ

1 голос
/ 15 января 2020

Это использование addAll вместо add, но существуют упрощения:

List<ResultlinevaluesEntity> res = new ArrayList<>();
for (List<ResultlinevaluesEntity> actBwa : getAct_Bwa()) {
    res.add(actBwa);
}

List<ResultlinevaluesEntity> res = new ArrayList<>();
res.addAll(getAct_Bwa());

List<ResultlinevaluesEntity> res = new ArrayList<>(getAct_Bwa());

После редактирования вопроса: ( не требуется параметр типа T)

Существует (иногда неизбежный) (анти) шаблон параллельных иерархий классов

Если у вас есть базовый класс элемента / сущности ItemBase.

class ItemBase
class ItemA extends ItemBase
class ItemB extends ItemBase

И базовый класс контейнера ContainerBase

class ContainerBase<T extends ItemBase>
    List<T> items
    List<T> getItems();

class ContainerA extends ContainerBase<ItemA>
class ContainerB extends ContainerBase<ItemB>

Это хороший способ иметь безопасные с типом классы с различием между List<ItemA> и List<ItemB>. В противном случае вы могли бы иметь только List<ItemBase>.

Лучше всего было бы , а не , чтобы нуждаться в ContainerA и ContainerB.

Вы также можете сделать (если вы этого не сделаете хочу параметр):

class ContainerBase
    List<ItemBase> items;
    public List<ItemBase> getItems();

class ContainerA extends ContainerBase
    @Override
    public List<ItemA> getItems() {
        return items.stream().map(ItemA.class::cast).collect(Collectors.toList());
    }

class ContainerB extends ContainerBase
    @Override
    public List<ItemB> getItems() {
        return items.stream().map(ItemB.class::cast).collect(Collectors.toList());
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...