0

我有一个阶级层次,

Class b extends class a 
Class c extends class a

这三个类都可以实例化。现在这三种类型的对象被添加到一个Set.

我需要遍历这个集合并找出类型 c 的实例,然后对其进行一些处理。

目前我正在遍历集合并检查每个条目是否为 instanceof c 。

有没有更好的方法来做到这一点?Collections图书馆本身的东西?

4

5 回答 5

1

您没有准确指定您想要的行为。听起来您只想要 的确切实例c,而不是派生自 的任何类的实例c

如果是这种情况,请使用Object.getClass

x.getClass().equals(c.class);

如果x是 的实例,则为真,如果是派生自的类的实例c则不为真。xc

如果不是这种情况,请使用instanceof

x instanceof c

如果是x实例c,则为真,如果是派生自的类的实例,则为真。xc

无论您选择哪一个,您都想从那里使用迭代器:

Iterator<a> iter = set.iterator();
while(iter.hasNext()) {
    a item = iter.next()
    if(item[.getClass().equals(c.class)| instanceof c]) {
        // do something with item
    }
}

当然,这是一种常见的模式,也有封装这种逻辑的库。

于 2013-06-20T13:08:04.740 回答
1

您可以选择索引每个插入对象的类,但这主要取决于 Set 中有多少项目以及 C 实例的速率。

这是一个示例类:

public class IndexedSet<T> {
  private Map<T,T> container = new HashMap<T,T>();
  private Map<Class<?>, Map<T,T>> indexByClass = new IdentityHashMap<Class<?>, Map<T,T>>();

  public boolean add(T e) {
    if (e == null) {
      throw new IllegalArgumentException("Can't add null");
    }
    if (container.containsKey(e)) return false;

    container.put(e, e);
    Map<T,T> indexEntry = indexByClass.get(e.getClass());
    if (indexEntry == null) {
      indexEntry = new IdentifyHashMap<T,T>();
      indexByClass.put(e.getClass(), indexEntry);
    }
    indexEntry.put(e,e);
    return true;
  }

  public boolean remove(T e) {
    e = container.remove(e);
    if (removed == null) return false;

    Map<T,T> indexEntry = indexByClass.get(e.getClass());
    indexEntry.remove(e);

    return true;
  }

  public Set<T> getAll() {
    return Collections.unmodifiableSet(container.keySet());
  }

  public Set<T> getByClass(Class<?> clazz) {
    Map<T,T> indexEntry = indexByClass.get(clazz);
    return indexEntry != null ? Collections.unmodifiableSet(indexEntry.keySet()) : null;
  }
}
于 2013-06-20T13:26:59.120 回答
1

您可以使用 aSetMultimap<Class<?>, A>从具体类映射到该类的一组实例,并且仍然具有与原始集合中的方法containsValue相对应的contains方法。

于 2013-06-20T13:31:21.313 回答
1

您可能想研究lambdaj。它允许您以函数式编程方式操作集合。像这样做一个谓词:

Matcher<A> f = new Predicate<A>() {
    public boolean apply(A item) {
        return item instanceof C;
    }
};

然后只需使用该谓词进行过滤。简单的!

filter(f, collection)

更多信息,这里有一篇博客文章概述了各种方法: http: //guidogarcia.net/blog/2011/10/29/java-different-ways-filter-collection/

于 2013-06-20T13:10:45.270 回答
1

不确定这是否适合您,但您可以使用 Google Guava 并在该集合上使用过滤器。让您的 Predicate 执行 instanceof 逻辑,然后如果为 true,它将根据该逻辑过滤集合。

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Sets.html

于 2013-06-20T13:10:59.120 回答