Коллекция Java, которая включает экземпляры подклассов - PullRequest
0 голосов
/ 07 февраля 2019

Мне нужно использовать коллекцию подклассов базового класса, вот описание проблемы:

class A {
}

class B extends A{
}

class C extends A{
}

class D extends A{
}

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

c.get(B.class);

Если у меня есть несколько экземпляров одного типа, я хочу получить экземпляр по типуи индекс: Примеры: c.get(B.class, 0), c.get(B.class, 1), c.get(C.class)

Любая помощь.

Ответы [ 3 ]

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

Похоже, что вы искали Java Map<K, V>.Вкратце, это коллекция пар ключ-значение.Вы можете сохранить значения, вызвав put(K, V), и получить доступ к ним, вызвав V get(K) Наиболее распространенная реализация - HashMap.Тем не менее, вы не сможете использовать Map<Class<T>, T>>, поскольку это не даст вам возможность хранить несколько значений для одного ключа, поэтому ваше решение будет хранить наборы значений в качестве значений вашей карты.Для этого вам потребуется король ленивой инициализации коллекции, такой как map.computeIfAbsent(key, k -> new ArrayList<>()) для Map Map<Class<T>, Collection<T>>

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

Как отмечалось в другом ответе, вы можете сделать это как Map, в противном случае вы также можете расширить коллекцию самостоятельно - это, к сожалению, не позволяет вам использовать, например.Перечислите интерфейс, чтобы вызвать его, но он работает, если вы используете сам класс.Это будет выглядеть примерно так:

class InstanceArrayList<T> extends ArrayList<T>
{
    public <V> V get(Class<V> instanceClass){
        return (V) this.stream()
            .filter( e -> e.getClass().equals( instanceClass ) )
            .findFirst()
            .orElse( null );
    }

    public <V> V get(Class<V> instanceClass, int index){
        return (V) this.stream()
            .filter( e -> e.getClass().equals( instanceClass ) )
            .skip( index ).findFirst()
            .orElse( null );
    }
}

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

И тогда вы можетепросто используйте его так:

public static void main( String[] args )
    {
        InstanceArrayList<A> it = new InstanceArrayList<>();
        it.add( new A() );
        it.add( new A() );
        it.add( new B() );
        it.add( new B() );
        it.add( new C() );
        it.add( new C() );

        System.out.println(it.get( A.class ));
        System.out.println(it.get( A.class, 1 ));
        System.out.println(it.get( B.class ));
        System.out.println(it.get( B.class, 1 ));
        System.out.println(it.get( C.class ));
        System.out.println(it.get( C.class, 1 ));

    }

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

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

Это было бы лучше всего сделать, используя Map и List

Map<Class, List<? extends A>> map = new HashMap<>()

Затем вы добавите такой элемент:

void addElement(final A element)
    if (!map.containsKey(element.getClass())){
        map.put(element.getClass(), new LinkedList<>());
    }    
    map.get(element.getClass()).add(element);
}

и вы сможете получить n-й экземплярконкретный класс

map.get(<Class here>).get(n);

Я не знаю ни одной реализации Collection, которая обеспечивала бы удобный метод get(key, index), поэтому вам, вероятно, придется кодировать его самостоятельно.

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