0

I am breaking my head on this problem to find a suitable data type to use, but I am not able to settle with which one would be the most efficient and simple way to program this without using any third party libraries:

Problem: Consider Share prices for a N number of companies given for each month since year 1990 in a CSV file. Format of the file is as below with first line as header.

Year,Month,Company A, Company B,Company C, .............Company N 
1990, Jan, 10, 15, 20, , ..........,50 
1990, Feb, 10, 15, 20, , ..........,50 
. 
. 
. 

. 2013, Sep, 50, 10, 15............500

Output: List for each Company year and month in which the share price was highest.

I've considered using trees, Hashmap, Lists but I am unable to finalise THE ONE solution. I am a newbie to Java with a couple of weeks of Java coding experience so far. Any help in the form of pseudo code, program or what data type to use is appreciated.

1
  • What have you tried and how are you considering usage of HashMap or List? Commented Feb 28, 2014 at 3:16

2 Answers 2

2

Ok, there are countless way to do this but my favorite one is to create a Company class to hold the Company.name, Company.month, Company.year, Company.price and use the Map to add the data. The adding logic would then check the map to see if a company with the same name exist, if not exist or the new company price is larger simply put the new company data to the map with company name as key. Well, the following code is just for demonstrating the purpose, I would make use eclipse to generate the getters/setters and use those instead of direct member variable just like the demo. And this demo lack the reading and collecting company data from CSV file.

CompanyLoader.java

package org.cnci.poc;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class CompanyLoader {
   private List<Company> companies;
   private int lastReadIdx=0;

   public CompanyLoader() {
   }

   // Simply read the CSV and return the next set of company data
   private Company getNextCompanyData() {
      if (companies == null) {
         lastReadIdx = 0;
         try {
            loadCompanies();
         } catch (Exception e) {
         }
      }
      if (companies == null) return null;
      if (lastReadIdx < companies.size()) return companies.get(lastReadIdx++);
      return null;
   }

   public void loadCompanies() throws Exception {
      Scanner s = null;
      try {
         companies = new ArrayList<Company>();
         File f = new File("test.csv");
         System.out.println(f.getAbsolutePath());
         s = new Scanner(new FileInputStream(f));
         String[] headers = readLine(s);
         System.out.println("headers: " + Arrays.toString(headers));
         if (headers != null && headers.length >0) {
            String[] data = null;
            while ((data = readLine(s)) != null) {
               System.out.println("data: " + Arrays.toString(data));
               if (data.length != headers.length) {
                  companies = null;
                  throw new Exception("Invalid Data - headers count " + headers.length + " does not match with data count "+data.length);
               }
               String year = data[0];
               String month = data[1];
               for (int x=2; x<data.length; x++) {
                  double price = new Double(data[x]).doubleValue();
                  Company company = new Company(headers[x], year, month, price);
                  companies.add(company);
               }
            }
         }
      } finally {
         if (s != null) s.close();
      }
   }

   private String[] readLine(Scanner s) {
      if (s.hasNextLine()) {
         return s.nextLine().trim().split(",");
      }
      return null;
   }

   public void processCompanies() {
      Map<String, Company> companies = new HashMap<String, Company>();
      Company newCompany = null;

      // repeat until all company data processed from CSV file
      while ((newCompany = getNextCompanyData()) != null) {
         Company oldCompany = companies.get(newCompany.getName());
         if (oldCompany == null || newCompany.getPrice() > oldCompany.getPrice())
            companies.put(newCompany.getName(), newCompany);
      }
      // Done, now display the winners
      for (String name : companies.keySet()) {
         Company company = companies.get(name);
         System.out.println(company.getName() + " highest price " + company.getPrice() + " is " + company.getMonth() + " " + company.getYear());
      }
   }

   public static void main(String[] args) {
      CompanyLoader loader = new CompanyLoader();
      loader.processCompanies();
   }
}

Company.java

package org.cnci.poc;

public class Company {
   private String name;
   private String year;
   private String month;
   private double price;

   public Company(String name, String year, String month, double price) {
      super();
      this.name = name;
      this.year = year;
      this.month = month;
      this.price = price;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getYear() {
      return year;
   }
   public void setYear(String year) {
      this.year = year;
   }
   public String getMonth() {
      return month;
   }
   public void setMonth(String month) {
      this.month = month;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }

   @Override
   public String toString() {
      return "Company [name=" + name + ", year=" + year + ", month=" + month + ", price=" + price + "]";
   }
}

test.csv

Year,Month,Company A,Company B,Company C,Company D,Company N 
1990, Jan, 10, 15, 20, 31, 50 
1990, Feb, 11, 14, 21, 30, 51 

output:

C:\Projects\Java\POC\test.csv
headers: [Year, Month, Company A,  Company B, Company C,  Company D,  Company N]
data: [1990,  Jan,  10,  15,  20,  31,  50]
data: [1990,  Feb,  11,  14,  21,  30,  51]
Company B highest price 15.0 is  Jan 1990
Company C highest price 21.0 is  Feb 1990
Company N highest price 51.0 is  Feb 1990
Company A highest price 11.0 is  Feb 1990
Company D highest price 31.0 is  Jan 1990
Sign up to request clarification or add additional context in comments.

5 Comments

Looks like a correct answer to me, except one thing: Use aBigDecimal object rather than a double primitive. A double is floating-point which trades accuracy for speed. Creating the double may introduce extra digits in the decimal fraction. As the Java Tutorial says: [double] should never be used for precise values, such as currency.
On second thought, as you are not doing any calculations with the numbers, in this particular case using a double is acceptable (rather than a BigDecimal). Generally a bad idea, but not here.
My thought exactly when I choose double, don't have to worry about overflow there without any calculation.
Any suggestion with the CSV parsing to fit the solution?
There you go, complete solution! Enjoy!
0

Well . you should read each line in as a String. Then, for each line after the title, you might follow one of several strategies: create an array of date, and an array of float for the stock price for each company

Or create a Company Object that itself has an array of for date and stock price)

you will need an "addDatePrice(date, price) method in the Company object. You can create the right number of companies from info in the title csv line (and give the Company object a nam)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.