Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best data structure to "group by" and aggregate values in Java?

I created an ArrayList of Array type like below,

ArrayList<Object[]> csvArray = new ArrayList<Object[]>();

As you can see, each element of the ArrayList is an array like {Country, City, Name, Age}.

Now I'm wanting to do a "group by" on Country and City (combined), followed by taking the average Age of the people for each Country+City.

May I know what is the easiest way to achieve this? Or you guys have suggestions to use data structures better than ArrayList for this "group by" and aggregation requirements?

Your answers are much appreciated.

like image 815
isaacniu Avatar asked May 04 '15 10:05

isaacniu


2 Answers

You will get lot of options in Java 8.

Example

 Stream<Person> people = Stream.of(new Person("Paul", 24), new Person("Mark",30), new Person("Will", 28));
 Map<Integer, List<String>> peopleByAge = people
.collect(groupingBy(p -> p.age, mapping((Person p) -> p.name, toList())));
 System.out.println(peopleByAge);

If you can use Java 8 and no specific reason for using a data structure, you can go through below tutorial

http://java.dzone.com/articles/java-8-group-collections

like image 74
Shineed Basheer Avatar answered Oct 27 '22 10:10

Shineed Basheer


You could use Java 8 streams for this and Collectors.groupingBy. For example:

final List<Object[]> data = new ArrayList<>();
data.add(new Object[]{"NL", "Rotterdam", "Kees", 38});
data.add(new Object[]{"NL", "Rotterdam", "Peter", 54});
data.add(new Object[]{"NL", "Amsterdam", "Suzanne", 51});
data.add(new Object[]{"NL", "Rotterdam", "Tom", 17});

final Map<String, List<Object[]>> map = data.stream().collect(
        Collectors.groupingBy(row -> row[0].toString() + ":" + row[1].toString()));

for (final Map.Entry<String, List<Object[]>> entry : map.entrySet()) {
    final double average = entry.getValue().stream()
                                .mapToInt(row -> (int) row[3]).average().getAsDouble();
    System.out.println("Average age for " + entry.getKey() + " is " + average);
}
like image 39
Jesper Avatar answered Oct 27 '22 10:10

Jesper