Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Lambda Sort With Variable Method Reference

I have a statement:

searchResults.sort(Comparator.comparing(WCCTableRowData::getD));

where getD is an accessor in the class WCCTableRowData and searchResults is a list of WCCTableRowData. The WCCTableRowData class has accessors from getA through getZ. I need to be able to set the sort field on the fly from a passed in variable. Is there an elegant way to do this or will I need a series of if statements or similar?

UPDATE 1 Unfortunately, neither approach in the accepted answer worked though I think in general the direction is correct. With approach 2 I get:

Intelli Sense

With approach 1, row.getField does not pick up the getField method in WCCTableRowData class and I get similar "does not conform to upper bound(s)" error. I think the error is saying that WCCTableRowData class has to implement Comparable?

like image 244
32U Avatar asked Feb 07 '23 08:02

32U


2 Answers

One way is to add a method in WCCTableRowData that can be given a field name and returns the value of that field.

class WCCTableRowData {
    Comparable<?> getField(String name) { ... }
}

String name = "C";
searchResults.sort(Comparator.comparing(row -> row.getField(name)));

If you don't want to modify the class, then you could set up an external map.

Map<String, Function<WCCTableRowData, Comparable<?>>> getters = new HashMap<>();
getters.put("A", WCCTableRowData::getA);
getters.put("B", WCCTableRowData::getB);
getters.put("C", WCCTableRowData::getC);

String name = "C";
searchResults.sort(Comparator.comparing(getters.get(name)));
like image 161
John Kugelman Avatar answered Mar 12 '23 01:03

John Kugelman


One way would be to store method references in a map with keys - values of your variable. It would be analogue of switch statement. You can use guava ImmutableMap.<WCCTableRowData, Comparable<?>>of() to make it a bit nicer.

Update

You can explicitly tell that comparator which is constructed by Comparator.comparing(...) is comparing Comparable :

Comparator.<WCCTableRowData, Comparable>comparing(getters.get(name));

Also you can just store comparators of your object (sounds much more reasonable but adds boilerplate), not functions returning comparables:

Map<String, Comparator<WCCTableRowData>> comparators = new HashMap<>();
comparators.put("A", Comparator.comparing(WCCTableRowData::getX));
comparators.put("B", Comparator.comparing(WCCTableRowData::getY));

String name = "C";
searchResults.sort(comparators.get(name)); 
like image 34
featuredpeow Avatar answered Mar 12 '23 01:03

featuredpeow