While generic methods can be applied, they won't solve the actual scenario you're trying to solve for (an earlier edit of this answer was an attempt before I thought through it more).
Taking a step back, this looks like the problem statement ("what" you're solving for, not "how"):
- Iterate all lists present in a map – in your posted code, this would be:
MultiValueMap<String, List> mvm
- Accomodate different object types – you posted Employee and Department as examples
- Whatever the list contains (Employee, Department, etc), you want to call
getDataElement()
As the other answer by Ausgefuchster describes, this can be solved with interfaces. I voted that answer up, but wanted to provide more
more detail and examples.
Step 1: define an interface
Regardless of concrete class, your map contains lists of things which have getDataElement(), so make an interface which captures that:
interface HasDataElement {
String getDataElement();
}
Step 2: classes implement the interface
For this answer, I made up a few simple classes – A, B, and C – which implement the interface, but otherwise only return a string when getDataElement() is called. In your code, you would modify Employee, Department, etc. to implement your new interface.
class A implements HasDataElement {
@Override
public String getDataElement() {
return "A";
}
}
class B implements HasDataElement {
@Override
public String getDataElement() {
return "B";
}
}
class C implements HasDataElement {
@Override
public String getDataElement() {
return "C";
}
}
Step 3: handle the map
I'm using built-in types, so Map<String, List> instead of your posted code which uses MultiValueMap<String, List>. I think this difference is not significant, but pointing it out anyway.
The method signature below specifies that the map isn't just <String, List>, but further specifies that the list itself must contain things which extend the HasDataElement interface: List<? extends HasDataElement>.
Inside the method, the same List<? extends HasDataElement> type shows up in the first loop.
Once inside, the concrete class of item isn't relevant – we know it conforms to the HasDataElement interface, so we can call item.getDataElement().
private static void processAllDataElements(Map<String, List<? extends HasDataElement>> map) {
for (List<? extends HasDataElement> list : map.values()) {
for (HasDataElement item : list) {
System.out.println(item.getDataElement());
}
}
}
Example usage
Here's a simple example, along with output, that creates a few different lists of the various classes A, B, and C. It then creates a map and adds all three lists.
List<A> listOfA = List.of(new A[]{new A()});
List<B> listOfB = List.of(new B[]{new B(), new B()});
List<C> listOfC = List.of(new C[]{new C(), new C(), new C()});
Map<String, List<? extends HasDataElement>> map = new HashMap<>();
map.put("A", listOfA);
map.put("B", listOfB);
map.put("C", listOfC);
processAllDataElements(map);
A
B
B
C
C
C