1

Working on a project and I need to be able to find the top three objects inside a list.

private List<Object> listOfObjects = new ArrayList<Object>();
listOfObjects.add(object1);
listOfObjects.add(object2);
listOfObjects.add(object2);
listOfObjects.add(object3);
listOfObjects.add(object3);
listOfObjects.add(object3);
listOfObjects.add(object4);

how would I display the top 3 re-occurring object in this list? The result I'm looking for is something like this.

Your top results are:
object3
object2
object1
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
codey
  • 25
  • 4

3 Answers3

1

If you are using Java 8, you can use Collectors.groupingBy to group your Object by number of occurrence like this :

Map<Object, Long> group = listOfObjects.stream()
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

To get the top three you can use :

group.entrySet().stream()
        .sorted(Map.Entry.<Object, Long>comparingByValue().reversed())
        .limit(3) // here you can use a variable for the number of the top object you want
        .forEach(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));

You have to @Override the equals and hashcode methods in your Object class.


I have a simple test I consider your object is a String for example :

List<Object> listOfObjects = new ArrayList<>();
listOfObjects.add("object1");
listOfObjects.add("object2");
listOfObjects.add("object2");
listOfObjects.add("object3");
listOfObjects.add("object3");
listOfObjects.add("object3");
listOfObjects.add("object4");

Outputs

object3 = 3
object2 = 2
object1 = 1
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • Thank you. This is basically it. Except I need to remove the reverse as I need object 3 = 1. – codey May 07 '18 at 12:45
  • You are welcome @codey But I don't understand why `object 3 = 1`! – Youcef LAIDANI May 07 '18 at 12:47
  • Because it's the most re-occurring object so I need it to be at the top. best way to iterate over it would be to have it as number 1 but I guess I could also go backwards! – codey May 07 '18 at 12:50
  • @codey My solution gives you `object3` as top one the number three means the number of occurrence not the classification – Youcef LAIDANI May 07 '18 at 12:52
1

If you are open to using a third-party library, Eclipse Collections has a Collector which can convert the List to a Bag. Bag is an unordered Collection which allows duplicates and internally maps items to counts. It also has special APIs for working with the occurrences of items.

List<ObjectIntPair<Object>> top3 =
        listOfObjects.stream()
                .collect(Collectors2.toBag())
                .topOccurrences(3);

The List here will (perhaps surprisingly) have four elements, as object1 and object4 will be considered both valid for third place. The method topOccurrences will leave it to you to decide how to handle the case where there are ties.

This code can also implemented using only Eclipse Collections APIs.

MutableList<String> list = Lists.mutable.with(
        "object1",
        "object2", "object2",
        "object3", "object3", "object3",
        "object4");

MutableList<ObjectIntPair<String>> top3 = 
        list.countBy(each -> each).topOccurrences(3);

The method countBy takes a Function, which in this case is just the element. There is also a Collectors2.countBy(Function).

Note: I am a committer for Eclipse Collections.

Donald Raab
  • 6,458
  • 2
  • 36
  • 44
0

I think that one of the most computationally efficient way (avoding looping several times over the list), could be to create another list and iterate over the initial list adding the items to the new list, before adding each item, you can ask if the new list already contains the object:

    List<Object> newList = new ArrayList<>();
    for(Object o : listOfObjects) {
        if(newList.contains(o)) {
            System.out.println(o);
        } else {
            newList.add(o);
        }
    }
mondaka
  • 362
  • 3
  • 12
  • How would I find the 3 most re-occurring objects in a list by using another list? Thanks for you answer! – codey May 07 '18 at 12:49
  • 1
    Sorry, my bad... I misunderstood your question, I read: "the three first re-occurring... ", in the same way I saw twice times the object1... summarizing, a disaster of aswer – mondaka May 08 '18 at 09:20