Reputation: 2973
Java program to alphanumeric sorting objects
please let me know how could i can get the expected result
Expected output : B2 D1 D2 D14 E2
Actual output : B2 D1 D14 D2 E2
====================================
List<Name> lst = new ArrayList<>();
lst.add(new Name("D",1));
lst.add(new Name("D",14));
lst.add(new Name("D",2));
lst.add(new Name("E",2));
lst.add(new Name("B",2));
Collections.sort(lst, new Comparator<Name>() {
@Override
public int compare(Name n1, Name n2) {
// TODO Auto-generated method stub
String o1=n1.getNm()+n1.getSeatnum();
String o2=n2.getNm()+n2.getSeatnum();
return o1.compareTo(o2);
}
});
for (Name name : lst) {
System.out.println(name.getNm()+name.getSeatnum());
}
=================================
public class Name {
private String nm;
private int seatnum;
public int getSeatnum() {
return seatnum;
}
public void setSeatnum(int seatnum) {
this.seatnum = seatnum;
}
public Name(String nm) {
super();
this.nm = nm;
}
public Name(String nm, int seatnum) {
super();
this.nm = nm;
this.seatnum = seatnum;
}
public String getNm() {
return nm;
}
public void setNm(String nm) {
this.nm = nm;
}
}
Upvotes: 3
Views: 685
Reputation: 201439
Yes it's possible, but your compare
function needs to first check the String
part for equality and then use a numerical comparison for the number part (currently, both are compared lexically). So, you could use something like -
public int compare(Name n1, Name n2) {
int c = n1.getNm().compareTo(n2.getNm());
if (c != 0) {
return c;
}
return Integer.valueOf(n1.getSeatnum()).compareTo(n2.getSeatnum());
}
Or in Java 8+ using Comparator.comparing(Function)
and Comparator.thenComparing(Function)
like
public int compare(Name n1, Name n2) {
return Comparator.comparing(Name::getNm).thenComparing(Name::getSeatnum)
.compare(n1, n2);
}
Upvotes: 4
Reputation: 723
You could rewrite your comparator to work in 2 steps:
Collections.sort(lst, new Comparator<Name>() {
@Override
public int compare(Name n1, Name n2) {
// compare the name part
int nameCompare = n1.getName().compareTo(n2.getName());
if(nameCompare != 0)
return nameCompare;
// compare the number part
return n1.getSeatnum() - n2.getSeatnum();
}
});
If you want to be aware of null
values you should add:
Collections.sort(lst, new Comparator<Name>() {
@Override
public int compare(Name n1, Name n2) {
// check for null Name
if(n1 == null && n2 == null)
return 0;
else if(n1 == null)
return -1;
else if(n2 == null)
return 1;
// check for null in nx.getName()
if(n1.getName() == null && n2.getName() == null)
return 0;
else if(n1.getName() == null)
return -1;
else if(n2.getName() == null)
return 1;
// compare the name part
int nameCompare = n1.getName().compareTo(n2.getName());
if(nameCompare != 0)
return nameCompare;
// compare the number part
return n1.getSeatnum() - n2.getSeatnum();
}
});
This approach would put null
values at the beginning of the list. If you prefer to have them at the end of the list, just swap 1
and -1
.
If you additionally want to be case-insensitive, modify the name compare line to:
int nameCompare = n1.getName().toLowerCase().compareTo(n2.getName().toLowerCase());
Upvotes: 0
Reputation: 2596
Just compare letters then your integers:
public int compare(Name n1, Name n2) {
// TODO Auto-generated method stub
int compare = n1.getNm().compareTo(n2.getNm());
if (compare == 0) {
return Integer.compare(n1.getSeatnum(), n2.getSeatnum());
} else {
return compare;
}
}
Upvotes: 1