I'm using Java 8 Comparators and I've the following code.
Model:
public class AreaModel { public long pinCode; public String rollNo; public AreaModel(long pinCode, String rollNo) { super(); this.pinCode = pinCode; this.rollNo = rollNo; } public long getPinCode() { return pinCode; } public void setPinCode(long pinCode) { this.pinCode = pinCode; } public String getRollNo() { return rollNo; } public void setRollNo(String rollNo) { this.rollNo = rollNo; } @Override public String toString() { return "["+pinCode+" "+rollNo+"]"; } }
Main:
import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; import com.javainuse.model.AreaModel; public class MainClass { public static void main(String[] args) { List<AreaModel> list = new ArrayList<AreaModel>(); list.add(new AreaModel(535005, "2")); list.add(new AreaModel(535006, "100")); list.add(new AreaModel(535007, "30")); list.add(new AreaModel(535005, "ROLE-45")); list.add(new AreaModel(535005, "ROLE-10")); list.add(new AreaModel(535005,"13")); list.add(new AreaModel(535005,"70")); Function<AreaModel, Long> retentionCodeSequence = AreaModel::getPinCode; Function<AreaModel, String> retentionDuration = AreaModel::getRollNo; // sort area by pincode, then by role Comparator<AreaModel> lastThenFirst = Comparator.comparing(retentionCodeSequence).thenComparing(retentionDuration,Comparator.reverseOrder()); list= list.stream().sorted(lastThenFirst).collect(Collectors.toList()); System.out.println("***"); System.out.println(list); } }
With that, the output what I'm getting is this
[[535005 ROLE-45], [535005 ROLE-10], [535005 70], [535005 2], [535005 13], [535006 100], [535007 30]]
And what I'm expecting is the following
[[535005 70], [535005 ROLE-45], [535005 13], [535005 ROLE-10], [535005 2], [535006 100], [535007 30]]
As you can see, even though pincodes have been sorted, roles haven't. And a role can contain whole number as a string or a number which is suffixed to a text. How do I resolve it?
Edit: updated question with possible values in the string
Assuming that all the valid values of the property rollNo
have the format "ROLE-XX"
, ie the prefix is the same and digits on the right are separated with a dash, you can use the following comparator , which makes use of the digit part of a rollNo
:
Comparator<AreaModel> lastThenFirst =
Comparator.comparing(AreaModel::getPinCode)
.thenComparing(
Comparator.<AreaModel>comparingInt(area -> Integer.parseInt(area.getRollNo().split("-")[1]))
.reversed()
);
As @g00se mentioned, the integer value in role should be parsed and used in the comparator.
Also, ToLongFunction
could be used to handle pinCode
and default List::sort
should be used to sort current list.
ToLongFunction<AreaModel> pinCode = AreaModel::getPinCode;
ToIntFunction<AreaModel> roleToInt = am -> Integer.parseInt(am.getRollNo().replaceAll("\\D", ""));
Comparator<AreaModel> byRoleDesc = Comparator.comparingInt(roleToInt).reversed();
// sort area by pincode, then by role
Comparator<AreaModel> byPinAndReversedRole = Comparator
.comparingLong(pinCode)
.thenComparing(byRoleDesc);
list.sort(byPinAndReversedRole);
// -> [[535005 70], [535005 ROLE-45], [535005 13], [535005 ROLE-10], [535005 2], [535006 100], [535007 30]]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.