Help please!! Arraylist Search/Count
Hi everyone,
I'm very new to Java. My problem is this:
I have created a program that parses many XML files. Now I want to generate a report of the number of files that contain each unique date within the xml files.
For example:
Using the Filewriter, I will like to write the number of files out of the 100 present that contain the following dates:
2005-07-12
2005-08-11
So far my attempts are to store all the dates parsed into an arraylist. I've tried using the popular wordcount.java and many other examples to no avail. If there are any methods out there that can help me count the unique items present in the arraylist, I will really appreciate it.
If I going about it the wrong way and there's a better way, can some also be shout it out.
Many many thanks
[825 byte] By [
Tellya] at [2007-11-26 13:03:24]

I don't get you. How about creating queriable objects representing your file's data, and then iterating over the list getting only those that match a date or whatever?
Have you consdiered storing the information in a slightly different manner. If you look into the Collections classes, you will see classes that allow you to store key value pairs - HashMap is the one that springs to mind. Why not have the date as the key and a running count of the number of occurrences as the value? It is possible to query the collection to say does this key exits, if not create a new mapping, if it does exits then get the value, increment by one and store it back again.
If you can able to store all the dates in an array list and want to find the uniques dates in that array list, then this program is enough...
import java.util.*;
import java.awt.*;
public class forTelly{
ArrayList al;
forTelly(){
al=new ArrayList();
String s[]={
"2005-07-12","2005-08-11","2005-07-12","2005-08-11",
"2005-04-12","2005-03-11","2005-02-12","2005-01-11",
};
for(int i=0;i<s.length;i++)
al.add(s[i]);
/* so now we can consider that your source
arraylist is al from this we are going to
find the number of unique dates...okay.....
*/
ArrayList aldest=new ArrayList();
/* we can create another array list in
which we will add all the unique date
*/
for(int i=0;i<al.size();i++){
if(aldest.size() >< 1) aldest.add(al.get(i));
else{
if(!aldest.contains(al.get(i)))
aldest.add(al.get(i));
}
}
System.out.println("So the number of unique address in the source Arr..Li...is:"+aldest.size());
}
public static void main(String args[]){
new forTelly();
}
}
Is this what you want?
Note: That < symbol may change to <> or >< so please correct it...
Thanks for the reply.
Infact its not only the dates that are an issue. I actually have many other objects that I will need to 'count' as it were. However, I used the dates as an example.
All of the elements a queriable objects. I'm able to read the data 'per instance (i.e. per metadata file parsed).
The dates therefore are objects but because they are compiled from the 100 individuals files I need to store them into place so as to sort them and count them eventually.
Any better?
Thanks
> Have you consdiered storing the information in a
> slightly different manner. If you look into the
> Collections classes, you will see classes that allow
> you to store key value pairs - HashMap is the one
> that springs to mind. Why not have the date as the
> key and a running count of the number of occurrences
> as the value? It is possible to query the collection
> to say does this key exits, if not create a new
> mapping, if it does exits then get the value,
> increment by one and store it back again.
Tillerman,
I think you are close understanding my problem. Do you have a solution to how I could keep the dates as a key and the occurrences as a count?
I will appreciate any mockup code.
Many thanks
> If you can able to store all the dates in an array
> list and want to find the uniques dates in that array
> list, then this program is enough...
> > import java.util.*;
> import java.awt.*;
>
> public class forTelly{
>ArrayList al;
> forTelly(){
> al=new ArrayList();
> String s[]={
>
> 2005-07-12","2005-08-11","2005-07-12","2005-08-11",
>
> 2005-04-12","2005-03-11","2005-02-12","2005-01-11",
> };
> for(int i=0;i<s.length;i++)
>al.add(s[i]);
>/* so now we can consider that your source
>arraylist is al from this we are going to
>find the number of unique dates...okay.....
> */
> rrayList aldest=new ArrayList();
> /* we can create another array list in
> which we will add all the unique date
>*/
> for(int i=0;i<al.size();i++){
> if(aldest.size() < 1)
> aldest.add(al.get(i));
>else{
>if(!aldest.contains(al.get(i)))
>aldest.add(al.get(i));
> }
> System.out.println("So the number of unique address
> in the source Arr..Li...is:"+aldest.size());
>
>}
> public static void main(String args[]){
> new forTelly();
>
> }
>
> Is this what you want?
> Note: That < symbol may change to <> or >< so please
> correct it...
pravinth,
Thanks for the code. I've already tried this snippet and it doesn't quite do what I need it to do as I have to cast the arraylist of objects to an string array and then even when I do it still prints all the dates with the number of occurences instead of a simply summary of say:
2005-07-12: 2 files
2005-08-11: 2 files
2005-01-11: 1 files
etc. etc.
Will appreciate any further thought on this.
Thanks,
But Telly i think this is a simple solution only.
You can type cast into string then try like this:
import java.util.*;
import java.awt.*;
public class forTelly{
ArrayList al,aldest;
forTelly(){
al=new ArrayList();
aldest=new ArrayList();
Object s[]={
"2005-07-12","2005-08-11","2005-07-12","2005-08-11",
"2005-04-12","2005-03-11","2005-02-12","2005-01-11",
};
for(int i=0;i<s.length;i++)
al.add(s[i]);
for(int i=0;i<al.size();i++){/*below >< may change into >< plz correct it... */
if(aldest.size()<1) aldest.add(al.get(i));
else{
if(!aldest.contains(al.get(i)))
aldest.add(al.get(i));
}
}
int no[]=new int[aldest.size()];
for(int j=0;j<aldest.size();j++){
for(int i=0;i<al.size();i++){
if(al.get(i).equals(aldest.get(j))) no[j]++;
}
}
for(int i=0;i<aldest.size();i++)
System.out.println(aldest.get(i)+":"+no[i]+"files");
}
public static void main(String args[]){
new forTelly();
}
}
>
Sorry for the dealy; just battled home through traffic!!
Here is a bit of code for you;
import java.util.Hashtable;
import java.util.Enumeration;
public class DateCount {
private Hashtable<String, Occurrence> dates = null;
public DateCount() {
// Note the typing of the Hashtable to save explicit casts later
this.dates = new Hashtable<String, Occurrence>();
}
public void countDates(String[] dateArray) {
String strDate = null;
Occurrence occ = null;
// Get each element from the array of dates
for(String date : dateArray) {
// Check if the Hashtable already contains an entry for this
// String (date)
if(dates.containsKey(date)) {
// If it does, recover the matching Occurrence object
occ = dates.get(date);
// And increment the count by one
occ.increment();
}
else {
// If a match was not found for the date, create an new
// instance of the Occurrence class and store it into
// the Hashtable using the String (date) as the key
dates.put(date, new Occurrence());
}
}
}
public String getResults() {
// Using StringBuffer to assemble the results string
StringBuffer buffer = new StringBuffer();
// Will hold each kesy value recovered from Enumeration
String key = null;
// Will hold the Occurrence object
Occurrence occ= null;
// Get an Enumeration over the Hashtables keys
Enumeration<String> keys = dates.keys();
// While there are still keys to be processed
while(keys.hasMoreElements()) {
// Get a key
key = keys.nextElement();
// Recover the matching Occurrence object
occ = dates.get(key);
// Append the info to the StringBUffer. The key (date) first
buffer.append(key);
// Next a comma to separate
buffer.append(", ");
// Then the number of occurrences
buffer.append(occ.getOccurrences());
// Finally, end this line with a carriage return
buffer.append(System.getProperty("line.separator"));
}
// Convert StringBuffers contents into a String, trim and return
return(buffer.toString().trim());
}
public static void main(String[] args) {
// Create an instance of the DateCount class
DateCount dc = new DateCount();
// Pass the cointDates() method an array of Strings containing dates.
dc.countDates(new String[]{"10/10/2006",
"01/05/2004",
"30/01/2003",
"10/10/2005",
"02/05/2004",
"10/10/2006",
"10/10/2006",
"01/01/1994",
"02/07/1987",
"02/09/2004",
"01/01/1995",
"10/10/2006",
"01/01/1994",
"02/09/2003",
"02/09/2004",
"02/09/2003"});
// Print out the results
System.out.println(dc.getResults());
}
}
// All this class does is wrap a primitive int value and provide methods to
// increment it and get the total.
public class Occurrence {
private int count = 0;
// Constructor to establish intial value; 1 in this case
public Occurrence() {
count = 1;
}
// Add one to the count
public void increment() {
this.count++;
}
// Return the total number of occurrences, the count
public int getOccurrences() {
return(count);
}
}
As you can see, there are two classes; DateCount and Occurrence (not very well named I know but well.....)
Occurrence simply warps a primitive int and provides methods that allow you to increment the count and get the total count. There will be one Occurrence obhject for each unique date. If there are matching dates then we simply increment the relevant Occurrence object's count.
All of the action takes place in the DateCount class. Take a look at the countDates() method in detail. It is passed an array of String(s) where each element is a 'date', I used this just for testing and I am sure that once you get the idea, you can modify it so that the technique works for you. Anyway, all I do is get an element from the array, check to see if an entry already exists in the Hashtable for this 'date'. If I find one, then I get the associated Occurrence object and increment the count, if there is no match, I create a new entry in the Hashtable where the 'date' is the key and a new Occurrence object the value.
Remember that the Hashtable will store key/value pairs. I have chosen to make the 'date' into the key and an instance of the Occurrence class into the value.
At the end, all I do is call the getResults() metjod of the DateCount class to, well, get the results. It is the main() method of the DateCoutn class that drives this whole example, so compile both classes and run that one.
Hope that is clear, if not just drop me an e-mail.
> Sorry for the dealy; just battled home through
> traffic!!
>
> Here is a bit of code for you;
>
> import java.util.Hashtable;
> import java.util.Enumeration;
>
> public class DateCount {
>
> private Hashtable<String, Occurrence> dates = null;
>
> public DateCount() {
> // Note the typing of the Hashtable to save
> ve explicit casts later
> this.dates = new Hashtable<String, Occurrence>();
> }
>
> public void countDates(String[] dateArray) {
> String strDate = null;
> Occurrence occ = null;
> // Get each element from the array of dates
> for(String date : dateArray) {
> // Check if the Hashtable already contains an
> an entry for this
> // String (date)
> if(dates.containsKey(date)) {
> // If it does, recover the matching Occurrence
> ence object
> occ = dates.get(date);
> // And increment the count by one
> occ.increment();
> }
> else {
> // If a match was not found for the date, create
> eate an new
> // instance of the Occurrence class and store it
> e it into
> // the Hashtable using the String (date) as the
> the key
> dates.put(date, new Occurrence());
> }
> }
>
> }
>
> public String getResults() {
> // Using StringBuffer to assemble the results
> ts string
> StringBuffer buffer = new StringBuffer();
> // Will hold each kesy value recovered from
> om Enumeration
> String key = null;
> // Will hold the Occurrence object
> Occurrence occ= null;
> // Get an Enumeration over the Hashtables keys
> Enumeration<String> keys = dates.keys();
> // While there are still keys to be processed
> while(keys.hasMoreElements()) {
> // Get a key
> key = keys.nextElement();
> // Recover the matching Occurrence object
> occ = dates.get(key);
> // Append the info to the StringBUffer. The key
> key (date) first
> buffer.append(key);
> // Next a comma to separate
> buffer.append(", ");
> // Then the number of occurrences
> buffer.append(occ.getOccurrences());
> // Finally, end this line with a carriage return
> buffer.append(System.getProperty("line.separator"))
> ;
> }
> // Convert StringBuffers contents into a String,
> g, trim and return
> return(buffer.toString().trim());
> }
>
> public static void main(String[] args) {
> // Create an instance of the DateCount class
> DateCount dc = new DateCount();
> // Pass the cointDates() method an array of Strings
> gs containing dates.
> dc.countDates(new String[]{"10/10/2006",
>"01/05/2004",
>"30/01/2003",
>"10/10/2005",
>"02/05/2004",
>"10/10/2006",
>"10/10/2006",
>"01/01/1994",
>"02/07/1987",
>"02/09/2004",
>"01/01/1995",
>"10/10/2006",
>"01/01/1994",
>"02/09/2003",
>"02/09/2004",
>"02/09/2003"});
> // Print out the results
> System.out.println(dc.getResults());
> }
>
> }
>
> // All this class does is wrap a primitive int value
> and provide methods to
> // increment it and get the total.
> public class Occurrence {
>
> private int count = 0;
>
> // Constructor to establish intial value; 1 in this
> s case
> public Occurrence() {
> count = 1;
> }
>
> // Add one to the count
> public void increment() {
> this.count++;
> }
>
> // Return the total number of occurrences, the
> e count
> public int getOccurrences() {
> return(count);
> }
>
> }
>
> As you can see, there are two classes; DateCount and
> Occurrence (not very well named I know but
> well.....)
>
> Occurrence simply warps a primitive int and provides
> methods that allow you to increment the count and get
> the total count. There will be one Occurrence obhject
> for each unique date. If there are matching dates
> then we simply increment the relevant Occurrence
> object's count.
>
> All of the action takes place in the DateCount class.
> Take a look at the countDates() method in detail. It
> is passed an array of String(s) where each element is
> a 'date', I used this just for testing and I am sure
> that once you get the idea, you can modify it so that
> the technique works for you. Anyway, all I do is get
> an element from the array, check to see if an entry
> already exists in the Hashtable for this 'date'. If I
> find one, then I get the associated Occurrence object
> and increment the count, if there is no match, I
> create a new entry in the Hashtable where the 'date'
> is the key and a new Occurrence object the value.
>
> Remember that the Hashtable will store key/value
> pairs. I have chosen to make the 'date' into the key
> and an instance of the Occurrence class into the
> value.
>
> At the end, all I do is call the getResults() metjod
> of the DateCount class to, well, get the results. It
> is the main() method of the DateCoutn class that
> drives this whole example, so compile both classes
> and run that one.
>
> Hope that is clear, if not just drop me an e-mail.
Many thanks Tillerman,
I'm still playing around with the code. I'm in the UK so I guess there will be a time-lag (if you are in the States that is).
Will get in touch via email if I'm still stuck.
Thanks,
Telly
You can use a bag: http://forum.java.sun.com/thread.jspa?threadID=5117518&tstart=50
Hi Pravinth,
You are right the solution is very simple. Your code works superbly. I stripped the main code from the class and embedded it into my main class and then cast my arraylist to a string array and bingo! So I'm going to award you Duke dollars.
Many many thanks,
Telly
> So I'm> going to award you Duke dollars.> Hallelujah! An honest poster.
> > So I'm
> > going to award you Duke dollars.
> >
>
> Hallelujah! An honest poster.
Hallelujah, Amen!
In life I've learnt that honesty PAYS!! Whatever you do, you do for yourself. There's nothing more valuable than one's integrity.
Anyway, I've awarded 8 Dukes to Pravinth because he's solution was simply and straightforward whilst giving 2 Dukes to Tillerman simply because his code also works but gosh, I don't have a clue as to instantiating multiple clasess...Remember, I'M NEW TO JAVA!
Thanks for all ya help.
Telly.
Thanks for the reply Telly.
When you get the time give it another look over. The reason for having that wrapper class - Occurrence - was that it would be possible for you create other subclasses of this one to deal with counting other types of object; perhaps storing the original object inside the class along with the counter. Any questions just e-mail.