Marcus
Marcus

Reputation: 6717

Find matching string occurrence in an ArrayList<String>

I have an ArrayList<String> containing dates represented as Strings with the format yyyy-MM-dd, e.g:

ArrayList<String> dates = new ArrayList<>(); 
dates.add("1991-02-28");
dates.add("1991-02-28");
dates.add("1994-02-21");

I'd like to know the number of times the same String (date) appears in the list. In the example above, I'd like to achieve the following output:

1991-02-28, 2
1994-02-21, 1

I've tried the following code

    ArrayList<String> dates = new ArrayList<>();
    dates.add("1991-02-28");
    dates.add("1991-02-28");
    dates.add("1994-02-21");
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    HashMap<String, String> dateCount = new HashMap<String, String>();

    String first = dates.get(0);
    int count = 1;
    dateCount.put(first, String.valueOf(count));
    for (int i = 1; i < dates.size(); i++) {
        if (first.equals(dates.get(i))) {
            count++;
        } else {
            first = dates.get(i);
            dateCount.put(dates.get(i), String.valueOf(count));
            count = 0;
        }
    }
    for (String date : dates) {
        String occ = dateCount.get(date);
        System.out.println(date + ", " + occ);
    }

But it prints

1991-02-28, 1
1991-02-28, 1
1994-02-21, 2

I'm tired, stuck, and turning to SO as a last resort. Any help is appreciated.

Upvotes: 3

Views: 214

Answers (5)

Daniel Nugent
Daniel Nugent

Reputation: 43322

I may be missing something, but it looks like you could just do something simple like this, just keep the count of Dates in the HashMap, and iterate over the HashMap for the output:

    ArrayList<String> dates = new ArrayList<>();
    dates.add("1991-02-28");
    dates.add("1991-02-28");
    dates.add("1994-02-21");
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    HashMap<String, Integer> dateCount = new HashMap<String, Integer>();

    for (int i = 0; i < dates.size(); i++) {

        String date = dates.get(i);
        Integer count = dateCount.get(date);
        if (count == null){
          dateCount.put(date, 1);
        }
        else{
          dateCount.put(date, count + 1);
        }

    }
    for(String key : dateCount.keySet()){
        Integer occ = dateCount.get(key);
        System.out.println(key + ", " + occ);
    }

Output:

1991-02-28, 2
1994-02-21, 1

Upvotes: 3

dimo414
dimo414

Reputation: 48794

The data structure you're describing is commonly called a Multiset or Bag (and generally uses Integer as the value, not String).

Guava provides a very nice Multiset interface, which makes this operation trivial:

Multiset<String> counts = HashMultiset.create();
for(String date : dates) {
  counts.add(date);
}
System.out.println(counts);
[1991-02-28 x 2, 1994-02-21]

Even without Guava, you can fake a Multiset with a Map<T, Integer> and a little boilerplate:

Map<String, Integer> counts = new HashMap<>();
for(String date : dates) {
  Integer count = counts.get(date);
  if(count == null) {
    count = 0;
  }
  counts.put(date, count+1);
}
System.out.println(counts);
{1991-02-28=2, 1994-02-21=1}

Upvotes: 2

PNS
PNS

Reputation: 19895

If all that is required is just a count of the number of occurrences of each full string in a List<String> collection, there are numerous trivial ways in Java 7 (or earlier) for doing it - not necessarily the fastest ones, but working.

For example, one can create a Set from the list and iterate over all items in the set, calling Collections.frequency(list, item), where list is the List<String> collection and item is each string of the set iteration.

Here is a simple implementation:

  public static class FrequencyCount {
    public static void main(String[] args){
      java.util.ArrayList<String> dates = new java.util.ArrayList<>();
      dates.add("1991-02-28");
      dates.add("1991-02-28");
      dates.add("1994-02-21");
      java.util.Set<String> uniqueDates = new java.util.HashSet<String>(dates);
      for (String date : uniqueDates) {
        System.out.println(date + ", " + java.util.Collections.frequency(dates, date));
      }
    }
  }

Output:

1994-02-21, 1
1991-02-28, 2

Upvotes: 1

MitulShrivastava
MitulShrivastava

Reputation: 158

Here is the correct solution:

public class mainClass {

/**
 * @param args
 */
public static void main(String[] args) {
    // TODO Auto-generated method stub

    ArrayList<String> dates = new ArrayList<>();
    dates.add("1991-02-28");
    dates.add("1991-02-28");
    dates.add("1994-02-21");
    //SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
    HashMap<String, Integer> dateCount = new HashMap<String, Integer>();

    //          String first = dates.get(0);
    //          int count = 1;
    //          dateCount.put(first, String.valueOf(count));
    //          for (int i = 1; i < dates.size(); i++) {
    //              if (first.equals(dates.get(i))) {
    //                  count++;
    //              } else {
    //                  first = dates.get(i);
    //                  dateCount.put(dates.get(i), String.valueOf(count));
    //                  count = 0;
    //              }
    //          }

    for(int i= 0; i < dates.size();i++) 
    {
        if(dateCount.containsKey(dates.get(i)))
        {
            dateCount.put(dates.get(i),dateCount.get(dates.get(i))+1); 
        }
        else 
            dateCount.put(dates.get(i),1); 
    }
    for (String date : dates) {
        int occ = dateCount.get(date);
        System.out.println(date + ", " + occ);
    }

}

}

But, you need to traverse through the hashmap instead of ArrayList to get the desired ouput..

Hope This helps!

Upvotes: 2

Amir Afghani
Amir Afghani

Reputation: 38511

I haven't debugged your logic yet, but you can use Google Guava's index method to perform a groupBy.

Upvotes: 2

Related Questions