tags:

views:

547

answers:

3

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);
    }
}


+6  A: 

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.

Nick Fortescue
Thanks Nick, that works perfectly, and teaches me something important.
Ankur
A: 

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.

John Leidegren
John, I am polling a class (Price) within the same application. The Price class is updated only when I receive a new price - through a socket connection, so I am not polling someone else's service. I think that should be ok?
Ankur
If it's all within the same application, instead of polling why don't you trigger the snapshot action when you receive a new price event?
MrWiggles
We intend to have a pretty large subset of all traded securities (in the world) eventually being parsed and filtered through this application. Polling once a second although it sounds very frequent actually reduces the total resource requirement.
Ankur
Well, no. It doesn't matter if it's within the app or not do you really need updates every second? It's gonna consume unnecessary system resources and if the data haven't changed since last time, then every such operation (poll) is redundant. How do you justify the necessity poll that often?
John Leidegren
How can you possibly make a judgement on whether 1 second is execessive or not if you don't know the background of the problem or scenario being addressed? Unless your app is running within a 80's style casio watch, 1 second is hardly pushing it..
ng
It will be very unlikley that the prices won't have changed within a second. At the moment I have only got 4 security codes but with the entire set (forex, treasuries, stocks, options, etc.) it's pretty unlikely for nothing to have changed.
Ankur
its just advice, but generally, polling is not as good a solution as event callbacks. but of course, there are always exceptions.
Chii
You should use a callback/event firing. If there are too many events then you can coalesce them.
Steve Kuo
+1  A: 

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().

Jon Skeet