HashMap值为Collection

时间:2016-06-01 19:07:23

标签: java collections hashmap iterator

我有以下代码:

    HashMap<Integer, String> h = new HashMap<Integer, String>();
    h.put(1, "a");
    h.put(2, "b");
    h.put(3, "c");
    h.put(4, "d");

    System.out.println(h); //{1=a, 2=b, 3=c, 4=d}

    Collection<String> vals = h.values();
    System.out.println(vals); //[a, b, c, d]

    Iterator<String> itr = vals.iterator();

    while (itr.hasNext()) //a b c d 
    {
        System.out.print(itr.next() + " ");
    }

我的问题:

  1. h.values()返回h中值的集合视图。由于vals是一个接口,我们如何为接口分配一些值(它们无法实例化)?实现此接口的类在哪里?那个班级的目标在哪里?

  2. itr的同类问题。我们知道vals.iterator()会返回集合的第一个元素。我们如何将它分配给接口实例?

1 个答案:

答案 0 :(得分:2)

管理问题答案的基本原则称为Liskov's Substitution Principle,在这种情况下适用于分配给定接口实例的值(Collection,{{1} })一个类型是实现该接口的类的引用(例如Iterator,一些匿名类等)。

如果您看到AbstractCollection方法代码,您将在Java 8源代码中看到:

HashMap#values()

因此,您将被退回

  1. public Collection<V> values() { Collection<V> vs; return (vs = values) == null ? (values = new Values()) : vs; } final class Values extends AbstractCollection<V> { public final int size() { return size; } public final void clear() { HashMap.this.clear(); } ... } 类的一个实例,它扩展了实现Values的{​​{1}}或
  2. {8}的具体子类的实例(请参阅{8}中AbstractCollectionCollection的Java AbstractCollection中的values = new AbstractCollection<V>()
  3. 同样,根据LSP,这一切都是有效的。要了解所有这些是如何连接起来的,您需要了解JDK代码库。

    更多答案

      

    h.values()返回h的值的Collection视图。由于val是一个接口,我们如何为接口分配一些值(它们无法实例化)?

    准确地说,386不是接口,而是其实例。确实,你不能使用像AbstractMap.java这样的vals运算符来实例化一个接口Listener,但根据LSP,你总是可以实例化new的具体实现。接口并将其分配给类型为listener l = new Listener()的变量,例如Listener

      

    实现此接口的类在哪里?

    在这种情况下,它是Listener类或Listener listener = new SerialListener();类,如上所示。

      

    该班的对象在哪里?

    在某些情况下,它是匿名内部类的一个实例,它在定义时被实例化。

      

    我们知道vals.iterator()返回集合的第一个元素。

    不太对劲。它返回实现Values接口的类的实例。如果在返回的对象上调用AbstractCollection方法时,您将获得该集合的第一个元素(假设它不为空)。

      

    我们如何将它分配给接口实例?

    这个想法是一样的。如果赋值语句左侧的变量(Iterator符号的左侧)指的是接口,则右侧可以引用直接或间接实现该接口的对象的引用(通过继承层次结构)。