Reputation: 351
In case, I have an array of strings in the following format -
["synthia 16", "alicia 3", "alicia 2", "alicia 1", "synthia 2"]
The list is to be sorted by name first and then the following number. The output of sorting should be-
["alicia 1", "alicia 2", "alicia 3", "synthia 2", "synthia 16"]
I used comaparator to do this using Java:
import java.util.Comparator;
import java.util.Arrays;
public class SortList {
public static void main ( String[] args) {
String[] names = {"synthia 16", "alicia 4", "alicia 19", "alicia 1", "synthia 2"};
System.out.println("Unsorted list:\n ");
displayList(names);
Arrays.sort(names, new nameComparator());
System.out.println("\nSorted list:\n");
displayList(names);
}
public static void displayList(String[] names) {
for(String name:names) {
System.out.println(name);
}
}
private static class nameComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
String[] s1NameNumPair = s1.split(" ");
String[] s2NameNumPair = s2.split(" ");
if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) > 1) {
return 1;
} else if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) < 1) {
return -1;
} else {
Double n1 = Double.parseDouble(s1NameNumPair[1]);
Double n2 = Double.parseDouble(s2NameNumPair[1]);
if (n1 > n2) { return 1; }
else if (n1 < n2) { return -1; }
else { return 0; }
}
}
}
}
However, using comparator like this only sorts the array alphabetically by the name. Here's the output this code generates:
Unsorted list:
synthia 16
alicia 4
alicia 19
alicia 1
synthia 2
Sorted list:
alicia 1
alicia 19
alicia 4
synthia 2
synthia 16
How can I get the right sorted output?
Upvotes: 2
Views: 217
Reputation: 76
You can use a comparator like this :
Java 7
Comparator<String> comparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String[] strings1 = o1.split("\\s+");
String[] strings2 = o2.split("\\s+");
int firstCompare = strings1[0].compareTo(strings2[0]);
int secondCompare = Integer.valueOf(strings1[1]).compareTo(Integer.valueOf(strings2[1]));
return firstCompare*2 + secondCompare;
}
};
Java 8
Comparator<String> comparator =
(String o1, String o2)-> {
String[] strings1 = o1.split("\\s+");
String[] strings2 = o2.split("\\s+");
int firstCompare = strings1[0].compareTo(strings2[0]);
int secondCompare = Integer.valueOf(strings1[1]).compareTo(Integer.valueOf(strings2[1]));
return firstCompare*2 + secondCompare;
};
Upvotes: 1
Reputation: 532
Please change the comparison as below.
private static class nameComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
String[] s1NameNumPair = s1.split(" ");
String[] s2NameNumPair = s2.split(" ");
if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) > 1) {
return 1;
} else if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) < 0) { //here it should be <0 not <1
return -1;
} else {
Double n1 = Double.parseDouble(s1NameNumPair[1]);
Double n2 = Double.parseDouble(s2NameNumPair[1]);
if (n1 > n2) {
return 1;
} else if (n1 < n2) {
return -1;
} else {
return 0;
}
}
}
}
Upvotes: 1
Reputation: 838
You must check for > 0
and < 0
so that == 0
will go to else,
try below
if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) > 0) {
return 1;
} else if (s1NameNumPair[0].compareTo(s2NameNumPair[0]) < 0) {
return -1;
} else {
Double n1 = Double.parseDouble(s1NameNumPair[1]);
Double n2 = Double.parseDouble(s2NameNumPair[1]);
return n1.compareTo(n2);
}
Upvotes: 4
Reputation: 466
Change your nameComparator
to this:
private static class nameComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
String[] s1NameNumPair = s1.split(" ");
String[] s2NameNumPair = s2.split(" ");
int diff = s1NameNumPair[0].compareTo(s2NameNumPair[0]);
if (0 == diff) {
Double n1 = Double.parseDouble(s1NameNumPair[1]);
Double n2 = Double.parseDouble(s2NameNumPair[1]);
return n1.compareTo(n2);
}
return diff;
}
}
Upvotes: 2