Find match of string in ArrayList <String>

I have one ArrayList<String>

that contains dates represented as Strings with format yyyy-MM-dd

, for example:

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

      

I would like to know the number of times that the same String

(date) appears in the list . In the above example, I would like to get the following output:

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

      

I have 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 he prints

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

      

I got tired and stuck and turned to SO as my last resort. Any help is appreciated.

+3


source to share


5 answers


If all it takes is just the number of numbers in which each complete row occurs in the collection List<String>

, there are Java 7

(or earlier) many trivial ways to accomplish this - not necessarily the fastest, but working.

For example, you can create Set

from a list and iterate over all the elements in a set by calling Collections.frequency(list, item)

where list

is the collection List<String>

and item

is each row of the set iteration.

Here's 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

      

+1


source


I might be missing something, but it looks like you could just do something simple, just keep the date count in a HashMap and iterate over the HashMap for 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

      

+3


source


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

+2


source


Here's 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 go through the hashmap instead of the ArrayList to get the output you want.

Hope this helps!

+2


source


The data structure you are describing is usually called a Multiset or sum (and usually uses it Integer

as a value, not String

).

Guava provides a very nice Multiset

thing that 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 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}

      

+2


source







All Articles