Java - Возвращает набор всех объектов определенного типа T, где T передается методу - PullRequest
0 голосов
/ 21 мая 2018

Я хочу написать метод, который дает исходный набор A и тип T возвращает новый набор, содержащий все объекты типа T в A.

Я настроил тест сКласс Person и его подклассы Man и Woman вместе с классом World для размещения набора Person объектов.

public class World {

    public World() {
        this.people = new HashSet<Person>();
    }

    public void addPerson(Person person) {
        getAllPeople().add(person);
    }

    public void removePerson(Person person) {
        getAllPeople().remove(person);
    }

    public Set<Person> getAllPeople() {
        return people;
    }

    public <T> Set<T> getAllPeople(Class<T> cls) {
        Set<T> ItemsOfClass = new HashSet<>();
        // Incompatible type error on next line
        ItemsOfClass = getAllPeople().stream().filter(object -> object.getClass().equals(cls)).collect(Collectors.toSet());
        return ItemsOfClass;
    }

    public Set<Person> people;
}

Так что я бы хотел getAllPeople(Man.class)вернуть новый набор Man объектов.

Моя текущая реализация getAllPeople основана на следующих ответах: https://stackoverflow.com/a/17840541 и
https://stackoverflow.com/a/16727596
, хотя я не могу понять, как они должны соответствовать друг другу, если вообще.

Я не очень хорош в дженериках, поэтому любые объяснения / советы приветствуются.

Ответы [ 3 ]

0 голосов
/ 21 мая 2018

Здесь проблема, вероятно, заключается в присваивании:

 ItemsOfClass = getAllPeople().stream().filter(object -> object.getClass().equals(T)).collect(Collectors.toSet());

Созданный Set методом collect() не имеет тип Set<T>, даже если вы отфильтровали только объект, класс которого T.
На самом деле вы выполняете итерацию на Person.Таким образом, вы собираете Set<Person>
Таким образом, вы обязаны явно указывать Set<Person> в Set<T>, например:

 ItemsOfClass = (Set<T>) getAllPeople().stream()
                                       .filter(object -> object.getClass().equals(T))
                                       .collect(Collectors.toSet());

или Class::cast, например:

 ItemsOfClass =  getAllPeople().stream()
                              .filter(object -> object.getClass().equals(T))
                              .map(T::cast)
                              .collect(Collectors.toSet());
0 голосов
/ 21 мая 2018

У вас есть Stream<Person>, который вы пытаетесь собрать в Set<T>.Но Stream<Person> будет производить Set<Person>.

. Вы можете сопоставить свои Person экземпляры с T экземплярами и получить Stream<T>.

public <T> Set<T> getAllPeople(Class<T> cls) {
    Set<T> itemsOfClass = getAllPeople().stream()
              .filter(cls::isInstance)
              .map(cls::cast)
              .collect(Collectors.toSet());
    return itemsOfClass;
}

Это использует cls::isInstance в качестве предиката для поиска элементов класса cls и cls::cast в качестве средства отображения, чтобы рассматривать ваши элементы как T экземпляров вместо Person экземпляров.

0 голосов
/ 21 мая 2018

Сначала вы должны привести свой элемент внутрь потока:

public <T> Set<T> getAllPeople(Class<T> clazz) {
    return obj.stream().filter(object -> object.getClass().equals(clazz))
              .map(v -> (T) v).collect(Collectors.toSet());
}
...