Summary counts for a two-dimensional array...

I've created an array that is populated by asking a user for values.
Now I'm trying to create summary values based off the populated array(s).
Here is the format of the array:

outputData[j][0] = countryNameString;
outputData[j][1] = currencyNameString;
outputData[j][2] = internationalAmountString;
outputData[j][3] = dollarAmountString;
outputData[j][4] = paymentMethodString;
outputData[j][5] = stdDateFormat2.format(expenseDate);

The summary needs to count only those countries that have been entered in [j][0] and list them in alphabetical order.  The second summary gives a count of the payment method [j][4], and needs to list the payment method whether it is chosen or not.  These are to be listed in descending rank by count.  I have a switch/case that lists all payment methods.

Help.
BlueTraneAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

vk33Commented:
Sorry, could you supply some code of yours? Otherwise it looks like hometask which we're prohibited to do...
0
BlueTraneAuthor Commented:
Sure.  It's quite long but here's the for loop for getting info from the user and populating the array:

for (int i = 1; i<=200; i++)
{
      j = i - 1;
      boolean validDate = false;
      do
      {
            super.setDateMonth(currentMonth);
            super.setDateDay(currentDay);
            super.setDateYear(currentYear);
            GregorianCalendar expenseDateGreg = new GregorianCalendar(super.getDateYear(),
            super.getDateMonth() - 1, super.getDateDay());
            expenseDate = expenseDateGreg.getTime();
            expenseDateString = stdDateFormat.format(expenseDate);

            int start = expenseDateGreg.get(Calendar.DAY_OF_YEAR);
            int end = dateTodayGreg.get(Calendar.DAY_OF_YEAR);
            int daysBetween = end - start;

            if (expenseDateGreg.before(dateTodayGreg))
            {
                  if (daysBetween > 60)
                  {
                  String outputLine2 = "The date of the expense occured" +
                        "\nmore than 60 days ago.  Are you sure this is correct?";
                  int answer = JOptionPane.showConfirmDialog(null, outputLine2, "Contiune?", JOptionPane.YES_NO_OPTION);
                  if (answer == JOptionPane.YES_OPTION) validDate = true;
                  }
                  else validDate = true;
            }
            else
            {
                  String outputLine2 = "The date " + expenseDateString + " is a future date." +
            "\nPlease enter a valid date.";
                  JOptionPane.showMessageDialog (null, outputLine2);
            }
      }while (!validDate);

      super.setCountry();
      country = super.getCountry();

      super.setConvType();
      convType = super.getConvType();

      super.setTransForm();
      switch (super.getTransForm())
      {
            case 1: meaning = "Corporate American Express";
            break;
            case 2: meaning = "Corporate Visa";
            break;
            case 3: meaning = "Corporate Mastercard";
            break;
            case 4: meaning = "Personal American Express";
            break;
            case 5: meaning = "Personal Visa";
            break;
            case 6: meaning = "Personal Mastercard";
            break;
            case 7: meaning = "Personal Check";
            break;
            case 8: meaning = "Cash";
            break;
            case 9: meaning = "Bank Transfer";
            break;
            case 10: meaning = "Travelers Check";
            break;
            case 11: meaning = "Other";
            break;
            default: meaning = "Cash";
      }

      super.setAmount();
      String expAmount = Double.toString(super.getAmount());

      //calculations
      double calculatedAmt = super.conversion();

      String amtDol = "";
      double amtIntl = 0;
      if (convType == 1)
      {
            NumberFormat currency1 = NumberFormat.getCurrencyInstance();
            amtDol = currency1.format(calculatedAmt);
            amtIntl = super.getAmount();
      }
      else if (convType == 2)
      {
            NumberFormat currency1 = NumberFormat.getCurrencyInstance();
            amtDol = currency1.format(expAmount);
            calculatedAmt = Math.round(calculatedAmt*100)/100.0;
            amtIntl = calculatedAmt;
      }

      //totals
      dollars = super.getUSD();
      totalDol = totalDol + dollars;
      NumberFormat currency = NumberFormat.getCurrencyInstance();
      usdString2 = currency.format(totalDol);

      //prepare output format
      String countryNameString = super.getCountry()+ paddingChar;
      countryNameString = countryNameString.substring(0,20);

      String currencyNameString = super.getCurrencyName() + paddingChar;
      currencyNameString = currencyNameString.substring(0,25);

      String dollarAmountString = paddingChar + amtDol;
      int stringLength = dollarAmountString.length();
      dollarAmountString = dollarAmountString.substring(stringLength-19, stringLength);

      String internationalAmountString = currency.format(amtIntl);
      internationalAmountString = paddingChar + internationalAmountString.substring(1, internationalAmountString.length());
      stringLength = internationalAmountString.length();
      internationalAmountString = internationalAmountString.substring(stringLength-19, stringLength);

      String paymentMethodString = "-------" + meaning;
      DateFormat stdDateFormat2 = DateFormat.getDateInstance(DateFormat.SHORT);


      //add lines to output array
      outputData[j][0] = countryNameString;
      outputData[j][1] = currencyNameString;
      outputData[j][2] = internationalAmountString;
      outputData[j][3] = dollarAmountString;
      outputData[j][4] = paymentMethodString;
      outputData[j][5] = stdDateFormat2.format(expenseDate);


      moreIn = JOptionPane.showInputDialog(null, "Do you wish to enter more data? (Yes or No)",
                              PaneTitle, JOptionPane.PLAIN_MESSAGE);
      if (moreIn.equalsIgnoreCase("no")) break;
      recCount++;
*******************************************

Let me know if you need more.  It would be great to extract this info.  But if I have to create another array I will.
                  }
0
vk33Commented:
For displaying countries it's a quite simple task:

TreeSet countries = new TreeSet();
for (int i=0; i<outputData.length; i++)
   countries.add(outputData[i][0];
Iterator iter = countries.iterator();
while (iter.hasNext())
   System.out.println ((String)iter.next());

But I didn't get the point with the second summary. Do you need to calculate how many records have such payment method? I mean something like a table: Payment-method --> Number-of-records. Is it what you need?
0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

BlueTraneAuthor Commented:
> Do you need to calculate how many records have such payment method?

Yes.

I envision output to be:

Corporate American Express:  5
Corporate Visa: 4
etc: 3
etc: 2
etc: 0
etc: 0

And so on.  These should be listed in descending by counts.
0
objectsCommented:
store your summaries in Maps. eg.

Map countryCounts = new HashMap();

if (outputData[j][0]!=null && outputData[j][0].trim().length()>0)
{
   Integer count = (Integer) countryCounts.get(outputData[j][0]);
   if (count==null)
   {
      count = new Integer(0);
   }
   countryCounts.put(outputData[j][0], new Integer(count.intValue()+1));
}
0
vk33Commented:
HashMap payments = new HashMap();
// counting...
for (int i=0; i<outputData.length; i++) {
   String payment = (String)outputData[i][4];
   Long num = (Long)payments.get(payment);
   if (num != null)
      payments.put(payment,new Long(num.getLongValue() + 1));
   else
      payments.put(payment,new Long(1));
}
// displaying...
for (int i=0; i<payments.size(); i++) {
   long max = 0;
   String maxKey = null;
   Iterator iter = payments.keySet().iterator();
   while (iter.hasNext()) {
      String payment = (String)iter.next();
      Long num = (Long)payments.get(payment);
      if (num.longValue() > max) {
         max = num.longValue();
         maxKey = payment;
      }
   }
   System.out.println (maxKey + ": " + max);
   payments.remove(maxKey);
}

Good luck!
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BlueTraneAuthor Commented:
How do I output this?  Forgive me, I'm quite a novice.
0
objectsCommented:
0
BlueTraneAuthor Commented:
You posted before I hit submit...Thanks.
0
BlueTraneAuthor Commented:
Wow thats a lot of stuff to learn that I'm not familiar with yet.
Is there another way without using collections?
Sorry if I'm being difficult.
0
objectsCommented:
> Is there another way without using collections?

if you know the number of categories you are summarizing you could do it with arrays, but I think you'd find it a lot easier by spending a little time to understan how maps work. It's really pretty simple, a map just consists of a number of key, value pairs.
To add a new pair to a map you use:

map.put(key, value);

and to get the value associted with a key you use:

value = map.get(key);

In your case the keys are what you are summarising by eg. country name
And the values are the summary counts.
0
BlueTraneAuthor Commented:
objects, once again thank you.  It does seem quite simple.
I'm pretty confident I can port over your country example to work with the payment types.

You're familiar with this program.  Once everything is stored in a map, how do I extract the counts for each value?  

0
objectsCommented:
You can use an Iterator to loop thru the elements:

Iterator i = map.keySet().iterator();
while (i.hasNext())
{
   String key = (String) i.next();
   Integer value = (Integer) map.get(key);
   ...
}
0
BlueTraneAuthor Commented:
When I go to test to make sure value is greater than 0 it says the operator cannot be used...

I'm I just retarded or what am I doing wrong?
0
BlueTraneAuthor Commented:
Ok, nevermind.  I see that that test is already built in right?

How about listing these countries alphabetically before printing?
0
BlueTraneAuthor Commented:
Here is what I've come up with:

//country map
Map countryCounts = new HashMap();
if (outputData[j][0]!=null && outputData[j][0].trim().length()>0)
{
         String countryName = (String)outputData[j][0];
         Integer count = (Integer) countryCounts.get(countryName);
      if (count==null)
            {
                        count = new Integer(0);
               }
      countryCounts.put(outputData[j][0], new Integer(count.intValue()+1));
}

//outputs country map
Iterator iter = countryCounts.keySet().iterator();
while (iter.hasNext())
{
         String countryName = (String) iter.next();
         Integer value = (Integer) countryCounts.get(countryName);
         summary = summary + countryName +": " + value +"\n";
}

//payments map
Map paymentCounts = new HashMap();
String paymentName = (String)outputData[j][4];
Integer count2 = (Integer)paymentCounts.get(paymentName);
if (count2 == null)
      count2 = new Integer(0);
paymentCounts.put(paymentName,new Integer(count2.intValue()+1));

//outputs payment map
Iterator iter2 = paymentCounts.keySet().iterator();
while (iter2.hasNext())
{
      String payment = (String)iter2.next();
      Integer value2 = (Integer)paymentCounts.get(payment);
      summary = summary +payment +": " + value2 +"\n";
      System.out.println(summary);
}

Not quite what I want as far as output goes.  Every key,value has its own line.  I would like for it to accumulate before outputting?
0
vk33Commented:
Hi once again. :)

Well, the code seems quite ok, but you do not sort the second summary. To make that just change a few lines:

for (int i=0; i<paymentCounts.size(); i++) {
   int max = 0;
   String maxKey = null;
   Iterator iter = paymentCounts.keySet().iterator();
   while (iter.hasNext()) {
      String payment = (String)iter.next();
      Integer num = (Integer)payments.get(payment);
      if (num.intValue() > max) {
         max = num.intValue();
         maxKey = payment;
      }
   }
   summary = summary + payment + ": " + num + "\n";
   payments.remove(maxKey);
}

Regards!
0
BlueTraneAuthor Commented:
hmmmm, I'm getting a null pointer error in the  new if statement...
0
vk33Commented:
really? Could you find out the payment which has null count?

      String payment = (String)iter.next();
      Integer num = (Integer)payments.get(payment);
      if (num == null)
         System.out.println (payment + " is null");
      else if (num.intValue() > max) {
         max = num.intValue();
         maxKey = payment;
      }

The situation seems quite impossible because you put a new Integer object in both cases when initializing the map...
0
BlueTraneAuthor Commented:
It goes on forever saying Corporate Mastercard is null over and over.
0
objectsCommented:
for (int i=0; i<paymentCounts.size(); i++) {
   int max = 0;
   String maxKey = null;
   Iterator iter = paymentCounts.keySet().iterator();
   while (iter.hasNext()) {
      String payment = (String)iter.next();
      Integer num = (Integer)payments.get(payment);
      if (num.intValue() > max) {
         max = num.intValue();
         maxKey = payment;
      }
   }
   summary = summary + payment + ": " + num + "\n";
   payments.remove(maxKey);
}

That doesn't look right, the for loop is looping over the payments summary, and then the while loop loops over it again. What is the intention here?


The NPE is because you are looping over one map, but gettin g the values out of a different one.

0
BlueTraneAuthor Commented:
I'll figure it out.  you guys answered my question.  I have to use a map.  Now I just have to learn it.
Thanks a lot.
0
objectsCommented:
0
vk33Commented:
2objects:
The main idea was the following: you find the biggest value (inner while loop), print it out and remove it from the hashmap. This should be repeated as many times as the number of elements in your map (for loop). That's it! :)

Regards!
0
objectsCommented:
Would be easier to just sort the values.
0
vk33Commented:
Yes, I was thinking this way too, maybe filling the TreeSet or something like that. But the problem is that we're interested in both key and value and the result should be sorted by value. Can you suggest the way to sort the map by value? Indeed, I didn't find an easy way for this myself. :)
0
objectsCommented:
You could try a TreeMap with a custom Comparator.
0
vk33Commented:
afaik, TreeMap keeps the nodes sorted by the key, not the value. And I'm not sure you can implement a comparator to compare the values instead of keys. I guess it's used before placing the node in the tree thus there's no value associated with the key at that moment. Am I right?
0
objectsCommented:
You can supply your own Comparator to the TreeMap ctor.
0
vk33Commented:
Sorry, objects, I think you can't. Comparator is applied when the node is placed in the tree. And it is applied to the Key only, Value is not touched. So, you cannot reference Value in your comparator code. Please, if I'm wrong, could you provide some code for the comparator.

Regards!
0
objectsCommented:
you could be right, was just a thought :)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.