每次使用.put()时都会重写HashMap

时间:2009-02-23 08:38:03

标签: java hashmap

我的申请与股票市场有关。我有一个不断更新名为Price的对象的Feed。 Price有一个存储安全代码(String)和价格(Double)的HashMap。每当新价格出现时,此对象都会更新。

该应用程序应该扫描大幅移动的价格。我有一个名为Poller的独立类,它每秒轮询Price对象并拍摄价格的快照。快照是如上所述的HashMap。然后我想将这个HashMap的价格与pollNumber一起存储在另一个HashMap中我以后可以传递pollNumber并在与该pollNumber对应的时间输出价格。

但相反,我得到所有以前的价格被覆盖并输出类似于下面的价格。

0:{MSFT = 17.67,AAPL = 93.85,GOOG = 333.86} {0 = {MSFT = 17.67,AAPL = 93.85,GOOG = 333.86}}

1:{MSFT = 17.64,AAPL = 93.85,GOOG = 334.02} {0 = {MSFT = 17.64,AAPL = 93.85,GOOG = 334.02},1 = {MSFT = 17.64,AAPL = 93.85,GOOG = 334.02}}

2:{MSFT = 17.64,AAPL = 93.85,GOOG = 334.08} {0 = {MSFT = 17.64,AAPL = 93.85,GOOG = 334.08},1 = {MSFT = 17.64,AAPL = 93.85,GOOG = 334.08}, 2 = {MSFT = 17.64,AAPL = 93.85,GOOG = 334.08}}

3:{MSFT = 17.65,AAPL = 93.83,GOOG = 334.08} {0 = {MSFT = 17.65,AAPL = 93.83,GOOG = 334.08},1 = {MSFT = 17.65,AAPL = 93.83,GOOG = 334.08},2 = {MSFT = 17.65,AAPL = 93.83,GOOG = 334.08},3 = {MSFT = 17.65,AAPL = 93.83,GOOG = 334.08}}

4:{MSFT = 17.64,AAPL = 93.83,GOOG = 334.07} {0 = {MSFT = 17.64,AAPL = 93.83,GOOG = 334.07},1 = {MSFT = 17.64,AAPL = 93.83,GOOG = 334.07},2 = {MSFT = 17.64,AAPL = 93.83,GOOG = 334.07},3 = {MSFT = 17.64,AAPL = 93.83,GOOG = 334.07},4 = {MSFT = 17.64,AAPL = 93.83,GOOG = 334.07}}

正如您所看到的那样,当我打印出应该具有不同价格序列的整个HashMap时,它们都是相同的。

基本上.put()函数会以某种方式覆盖旧条目。

如果你知道如何修复这种行为,那么HashMap(大的)每次都有一个新的价格序列条目。


public class Poller {

    private final int period=1000;
    private final int delay=1000;

    private static int pollNumber=0;
    private static HashMap<Integer,HashMap<String,Double>> 
        polledPrice = new HashMap<Integer, HashMap<String,Double>>();

    public void pollPrice(){

    Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
                public void run() {
                //    System.out.println(Price.getPricesMap());
System.out.println(pollNumber+" : "+Price.getPricesMap());
                    polledPrice.put(pollNumber, Price.getPricesMap());
                    System.out.println(polledPrice);
                    pollNumber = pollNumber+1;

                    Time atime = new Time();
                        atime.addToTimeMap(pollNumber);

                }
            }, delay, period);
    }
}

3 个答案:

答案 0 :(得分:6)

你需要复制HashMap,否则看起来你只是一遍又一遍地存储相同的Map,这当然会被覆盖。使用此行:

polledPrice.put(pollNumber, new HashMap(Price.getPricesMap()));

最简单的解决方法。

答案 1 :(得分:1)

问题是Price.getPricesMap()每次都返回对同一对象的引用。这对我来说听起来像是一个糟糕的API设计 - 或者至少有一个应该被记录下来。

可以通过在客户端代码(as suggested by Nick Fortescue)中进行复制或更改Price来解决此问题。后者可以在每次实际更改时创建不可变映射,也可以在每次调用时将副本返回getPricesMap()

答案 2 :(得分:0)

你真的需要每秒查看你所拥有的服务吗?这听起来有点像虐待我。您应该至少在每次轮询之间等待5-10秒,特别是如果这涉及请求Web资源。我认为尼克给了你足够好的答案,但过度的民意调查是邪恶的!不要这样做。