Reputation: 51100
My application is related to the stock market. I have a feed that is consistently updating an object called Price. Price has a HashMap that stores the security code (String) and price (Double). Every time a new price comes in this object is updated.
The application is supposed to scan the prices for large moves. I have a separate class called Poller which polls the Price object every second and takes snapshot of the prices. The snapshot is a HashMap as described above. I then want to store this HashMap of prices along with a pollNumber in another HashMap I can later pass the pollNumber and get out the prices at the time corresponding to that pollNumber.
But instead I get all the previous prices being overwritten and output similar to that below.
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}}
As you can see when I print the entire HashMap that should have different price series they are all the same.
Basically the .put() function is overwriting the old entries somehow.
If you know how to fix the behaviour so that the HashMap (the big one) has a new price series entry each time.
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);
}
}
Upvotes: 1
Views: 2197
Reputation: 1500065
The problem is that Price.getPricesMap()
is returning a reference to the same object each time. This sounds like a bad bit of API design to me - or at least one that ought to be documented.
It can be fixed either by making the copy in the client code (as suggested by Nick Fortescue) or by changing Price
. The latter could either create an immutable map each time there was an actual change, or return a copy on each call to getPricesMap()
.
Upvotes: 1
Reputation: 60987
Do you really need to poll what ever service you have every second? It sounds a bit like abuse to me. You should wait 5-10 seconds between each poll at least, especially if this involves requesting a web resource. I think Nick gave you a good enough answer but excessive polling is evil! Don't do it.
Upvotes: 0
Reputation: 44153
You need to take copy of the HashMap, otherwise it looks like you are just storing the same Map over and over again, which of course gets overwritten. Use this line:
polledPrice.put(pollNumber, new HashMap(Price.getPricesMap()));
As the simplest fix.
Upvotes: 6