HashSet中的Java动态对象存储

时间:2015-01-02 23:08:02

标签: java

我需要存储这样的模糊对象(每个都有自己的类):

ObjectA 
ObjectB
ObjectC

创建的HashSet看起来像:

public static HashSet<Object> objects = new HashSet<Object>();

然后我将对象一次放置一个:

object.add(new ObjectA());

然而,这是问题所在,如果稍后我需要通过迭代来检索这样的某些对象:

for(Object obj : objects){
    if(obj instanceof ObjectA){
        // print that the object is A
    }
}

什么都没发生,即使我知道ObjectA中唯一的对象是我得到了这个例外:

Caused by: java.lang.ClassCastException: java.util.HashSet$Node cannot be cast to ***.*****.******.objects.ObjectA

造成这种情况的原因是什么?为什么对象突然不是他们自己的一个实例?

2 个答案:

答案 0 :(得分:2)

此问题与泛型无关。这个问题与Java有关Object时不知道你想要什么样的for (Object obj : objects) { ... }

说明

我相信你输错了错误信息;我认为应该是这个(我强调的是):

  

引起:java.lang.ClassCastException:java.util.Hash Map $ Node无法转换为***。*****。** ****。objects.ObjectA

错误的原因是Java HashSet由值为HashMap的Java null支持。在HashMap内部使用HashMap$Node类来存储它的元素:

// from the Java source code for HashMap
/**
 * Basic hash bin node, used for most entries.  (See below for
 * TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
 */
// Inner class of HashMap - inner classes are always named like OuterClass$InnerClass in bytecode
static class Node<K,V> implements Map.Entry<K,V> { ... }

请记住,因为Java中的所有类最终都来自Object,所以当你像这样迭代一个HashSet时......

for (Object obj : objects){
    if(obj instanceof ObjectA){
        // print that the object is A
    }
}

... Object obj可以简单地任何。 Java 显然 找到它可以找到的Object的第一个匹配项,并确定存储元素的内部HashMap$Node类是否匹配对于Object(因为它是)。然后它继续迭代并为您提供HashMap$Node而不是您想要的实际值。 可能是您ClassCastException的原因 - 您获得了HashMap$Node而不是您想要的Objects

解决方案

由于所有对象都来自 Object ,因此告诉Java您想要实际值的唯一方法是在日期之前使用旧式Iterator<E>方法增强的 - for(这将取代你当前的for循环):

Iterator<Object> iter = objects.iterator();
Object obj;
while (iter.hasNext()) {
    obj = iter.next();
    if (obj instanceof ObjectA) {
        // ... do stuff ...
    }
}

这应该像您想要的那样工作,因为它保证只为您提供您的值,因为它在HashSet中实现如下:

// from the Java source code for HashSet
public Iterator<E> iterator() {
    return map.keySet().iterator(); // only get the keys from the underlying HashMap, i.e. the values.
}

答案 1 :(得分:1)

我们永远都不会知道OP写的是什么,但是这里是你在做类似于问题中所描述的事情的过程中如何能够合理地得到报告的错误消息。 (OP已确认错误消息是指HashMap $ Node,而不是HashSet $ Node)。这都是假设。 如果你喜欢这个,请upvote dudeprgm的答案,而不是我的

public class Main {

    static class ObjectA {}

    static class ObjectB {}

    static class ObjectC {}

    public static void main(String[] args) {
        Map<Object, Integer> map = new HashMap<>();
        map.put(new ObjectA(), 1);
        map.put(new ObjectB(), 2);
        map.put(new ObjectC(), 3);
        // objects will contain ObjectA, ObjectB and ObjectC instances. 
        Set<Object> objects = new HashSet<Object>();
        objects.add(new ObjectA());
        objects.add(new ObjectB());
        objects.addAll(map.entrySet()); // Here we mean to do map.keySet().
        for (Object obj : objects) {
            if (obj instanceof ObjectB) {
                ObjectB objB = (ObjectB) obj;
                // Do something with objB
            } else if (obj instanceof ObjectC) {
                ObjectC objC = (ObjectC) obj;
                // Do something with objC
            } else {
                ObjectA objA = (ObjectA) obj;
                // Do something with objA
            }
        }
    }
}