Java – HashMap vs Map对象

问题:

我创建的以下地图有什么区别(另一个问题是,人们使用它们看起来可以互换,我想知道如何/如何不同):

HashMap<String, Object> map = new HashMap<String, Object>();
Map<String, Object> map = new HashMap<String, Object>();

回答:

对象之间没有区别;在这两种情况下,您都有HashMap<String, Object>。在对象的interface中有一个区别。在第一种情况下,接口为HashMap<String, Object>,而在第二种情况下为Map<String, Object>。但是底层对象是一样的。
使用Map<String, Object>的优点是,您可以将基础对象更改为不同类型的地图,而不会破坏与使用它的任何代码的合同。如果您将其声明为HashMap<String, Object>,则如果要更改基础实现,则必须更改合同。
示例:假设我写这个类:

class Foo {
    private HashMap<String, Object> things;
    private HashMap<String, Object> moreThings;

    protected HashMap<String, Object> getThings() {
        return this.things;
    }

    protected HashMap<String, Object> getMoreThings() {
        return this.moreThings;
    }

    public Foo() {
        this.things = new HashMap<String, Object>();
        this.moreThings = new HashMap<String, Object>();
    }

    // ...more...
}

该类有一些string-> object的内部映射,它们通过子类与存储器方法共享。假设我用HashMap来写,因为我认为这是编写课程时使用的适当的结构。
后来,玛丽写了代码子类化的代码。她有一些与thingsmoreThings有关的东西,所以自然会把它放在一个常见的方法中,她在定义她的方法时使用与getThings getMoreThings相同的类型:

class SpecialFoo extends Foo {
    private void doSomething(HashMap<String, Object> t) {
        // ...
    }

    public void whatever() {
        this.doSomething(this.getThings());
        this.doSomething(this.getMoreThings());
    }

    // ...more...
}

后来我确定,如果在Foo中使用TreeMap而不是HashMap,情况会更好。我更新Foo,将HashMap更改为TreeMap。现在,SpecialFoo不再编译,因为我违反了合同:Foo曾经说过提供HashMap,但现在提供TreeMaps。所以我们现在必须修复SpecialFoo(这种事情可以通过一个代码库)。
除非我有一个非常好的理由分享我的实现使用HashMap(这确实发生),我应该做的是声明getThingsgetMoreThings,只是返回Map<String, Object>而不再具体比起那个来说。事实上,除了Foo之外,除非有理由去做别的事,否则我应该将thingsmoreThings声明为Map而不是HashMap TreeMap

class Foo {
    private Map<String, Object> things;             // <== Changed
    private Map<String, Object> moreThings;         // <== Changed

    protected Map<String, Object> getThings() {     // <== Changed
        return this.things;
    }

    protected Map<String, Object> getMoreThings() { // <== Changed
        return this.moreThings;
    }

    public Foo() {
        this.things = new HashMap<String, Object>();
        this.moreThings = new HashMap<String, Object>();
    }

    // ...more...
}

注意我现在如何使用Map<String, Object>到处可以,只有在创建实际对象时才具体。
如果我这样做,那么玛丽会做到这一点:

class SpecialFoo extends Foo {
private void doSomething(Map t) { // <== Changed // ... } public void whatever() { this.doSomething(this.getThings()); this.doSomething(this.getMoreThings()); } } [/code] ...和改变Foo不会使SpecialFoo停止编译。
接口(和基础类)让我们揭示only as much as is necessary,保持我们的灵活性在适当的范围内进行更改。一般来说,我们希望让我们的参考文献尽可能的基本。如果我们不需要知道它是HashMap,只需将其称为Map
这不是一个盲目的规则,但是总的来说,coding to the most general interface比编码更具体的脆弱性。如果我记得,我不会创建一个Foo,使SpecialFoo设置玛丽失败。如果Mary记得那个,那么尽管我搞砸了Foo,她会用Map而不是HashMap宣布私人方式,而我不断改变的Foo合同不会影响她的代码。
有时你不能这样做,有时你必须具体。但除非你有理由,否则会面向最不具体的界面。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Java – HashMap vs Map objects

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

− 3 = 7