I'm trying to solve a classic problem (find the top K elements in a random collection). I'm trying to do this with Generics, but I keep on getting strange "errors". I'm not sure if what I'm doing is the right way of doing these things, but I don't see another way to be honest.
Interface declaration
public interface TopK<T> {
T[] getMostOccurrences(T[] items, int k);
}
Implementation
public class TopKHeap<T> implements TopK<T> {
private T[] items;
private Map<T, Integer> occurrences;
@Override
public T[] getMostOccurrences(T[] items, int k) {
this.items = items;
countOccurrences();
PriorityQueue<T> minHeap = new PriorityQueue<>((n1, n2) -> occurrences.get(n1) - occurrences.get(n2));
for (T t : occurrences.keySet()) {
minHeap.add(t);
if (minHeap.size() > k) {
minHeap.poll();
}
}
List<T> topItems = new ArrayList<>(k);
for (int idx = k - 1; idx >= 0; idx--) {
topItems.add(0, minHeap.poll());
}
return (T[]) topItems.toArray();
}
private void countOccurrences() {
occurrences = new HashMap<>();
for (T t : items) {
occurrences.put(t, occurrences.getOrDefault(t, 0) + 1);
}
}
}
Test Case
@Test
public void testTopItems() {
String[] input = {
"John",
"John",
"John",
"Jane",
"Jane",
"Jane",
"Jane",
"Michael",
"Emily",
"Emily"
};
TopK<String> top = new TopKHeap<>();
assertThat(new String[]{"Jane", "John"}, Matchers.arrayContaining(top.getMostOccurrences(input, 2)));
}
I constantly get the following error:
java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String; ([Ljava.lang.Object; and [Ljava.lang.String; are in module java.base of loader 'bootstrap')
I've tried a couple of different approaches here. Initially I didn't use the ArrayList, but used T[] topItems = (T[]) new Object[k];
, which yielded the same result. I replaced the array with an ArrayList, because Collections in general are better in handling Generics in Java, but apparently that didn't solve it.
The question is two-fold I guess. Why does it keep on throwing that error? And second question is, what is a more elegant way to solve this problem? By problem I mean, creating a generic class that uses Arrays.
edit> The method itself runs fine, but the moment I create a reference to the result of the output, it throws the ClassCastException. So whenever I do this, it falls over:
String[] result = top.getMostOccurrences(input, 2);