Barlo
Barlo

Reputation: 86

Java - Get most common elements in arrayList of Object

I have an ArrayList that looks like this:

ArrayList<TravelData> listOfTravels;

and TravelData object contains the following elements

int id;
String groupName;
String guideName;

This is how I initialize the arrayList:

listOfTravels.add(new TravelData(1,"group a", "Ross"));
listOfTravels.add(new TravelData(2,"group a", "Chandler"));
listOfTravels.add(new TravelData(3,"group a", "Monica"));
listOfTravels.add(new TravelData(4,"group b", "Phoebe"));
listOfTravels.add(new TravelData(5,"group b", "Rachel"));
listOfTravels.add(new TravelData(6,"group c", "Joey"));
listOfTravels.add(new TravelData(7,"group c", "Rachel"));
listOfTravels.add(new TravelData(8,"group d", "Chandler"));

I want to get the top 3 most common groups and guides on that list. In this example:

Top 3 groups: "group a", "group b", "group c"
Top 3 guides: "Rachel", "Chandler", "Ross"

(The third place of guides could be anyone else because Ross, Monica, Phoebe and Joey have the same appearance count).

I found good answers like how to get the most common element in a list but it's only good for ArrayList of integers and shows only the first most common element.

Upvotes: 0

Views: 903

Answers (4)

Amad&#225;n
Amad&#225;n

Reputation: 748

This is a good use case for streams. The idea is, to first transform the List<TravelData> to Map<String, Integer> of group to number of guides (or guide to number of groups) and then sort that map by the numbers, take only the map's keys (groups/guide) and limit it to the first three elements.

I am assuming that TravelData has the methods String getGroup() and String getGuide():

Using Java 11 type inference in the example

final comparator = Comparator.comparing(Map::getValue)
                             .reversed();

final top3Groups = listOfTravels.stream().collect(Collectors.groupingBy(TravelData::getGroup(),
                                                                        Collectors.counting())
                                .entrySet()
                                .stream().sorted(comparator)
                                         .map(Map::getKey)
                                         .limit(3)
                                         .collect(Collectors.toList());

final top3Guides = listOfTravels.stream().collect(Collectors.groupingBy(TravelData::getGuide(),
                                                                        Collectors.counting())
                                .entrySet()
                                .stream().sorted(comparator)
                                         .map(Map::getKey)
                                         .limit(3)
                                         .collect(Collectors.toList());

Upvotes: 0

Mansur
Mansur

Reputation: 1829

Here's my solution with Streams.

// comparator for reverse sorting
Comparator<Map.Entry<String, Long>> reversed = Map.Entry.comparingByValue();
Comparator<Map.Entry<String, Long>> entryComparator = Collections.reverseOrder(reversed);

List<String> collect = listOfTravels.stream()
        .collect(Collectors.groupingBy(TravelData::getGuideName, Collectors.counting()))
        .entrySet()
        .stream()
        .sorted(entryComparator)
        .map(Map.Entry::getKey)
        .limit(3)
        .collect(Collectors.toList());
System.out.println(collect);

Upvotes: 0

Avvappa Hegadyal
Avvappa Hegadyal

Reputation: 273

Try this it will help you.

public class TravelData {
int id;
String groupName;
public String getGroupName() {
    return groupName;
}

public String getGuideName() {
    return guideName;
}

String guideName;

public TravelData(int id, String groupName, String guideName) {
    this.id = id;
    this.groupName = groupName;
    this.guideName = guideName;
}

public static void getcommonGroups(ArrayList<TravelData>  list){
    Map<String, Integer> wordMap = new HashMap<String, Integer>();

    for(TravelData td:list){
        if(wordMap.containsKey(td.getGroupName())){
            wordMap.put(td.getGroupName(), wordMap.get(td.getGroupName())+1);
        } else {
            wordMap.put(td.getGroupName(), 1);
        }
    }

    List<Map.Entry<String, Integer>> sortedList = sortByValue(wordMap);
    for(Map.Entry<String, Integer> entry:sortedList){
        System.out.println(entry.getKey()+" ===="+entry.getValue());
    } }

  public static List<Map.Entry<String, Integer>> sortByValue(Map<String, Integer> 
  wordMap)  {

    Set<Map.Entry<String, Integer>> set = wordMap.entrySet();
    List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(set);
    Collections.sort( list, new Comparator<Map.Entry<String, Integer>>()
    {
        public int compare( Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 )
        {
            return (o2.getValue()).compareTo( o1.getValue() );
        }
    } );
    return list;
}


public static  void main(String args[]){
    ArrayList<TravelData> listOfTravels=new ArrayList() ;
    listOfTravels.add(new TravelData(1,"group a", "Ross"));
    listOfTravels.add(new TravelData(2,"group a", "Chandler"));
    listOfTravels.add(new TravelData(3,"group a", "Monica"));
    listOfTravels.add(new TravelData(4,"group b", "Phoebe"));
    listOfTravels.add(new TravelData(5,"group b", "Rachel"));
    listOfTravels.add(new TravelData(6,"group c", "Joey"));
    listOfTravels.add(new TravelData(7,"group c", "Rachel"));
    listOfTravels.add(new TravelData(8,"group d", "Chandler"));
    getcommonGroups(listOfTravels);
}}

Upvotes: 2

Mihai Alexandru-Ionut
Mihai Alexandru-Ionut

Reputation: 48407

You could create a hashMap structure for groups where the key will be groupName and the value will be the number of occurences.

Then, just sort the hashMap structure by value descending and get the results.

Upvotes: 1

Related Questions