I've got two ArrayList<JLabel>
:
ArrayList<JLabel> label1 = new ArrayList<JLabel>();
ArrayList<JLabel> label2 = new ArrayList<JLabel>();
label1
contains names (like "John" or "car") and label2
contain ratings (like "8.5" or "10.0"). I wanna sort both lists by rating.
I've used Collections.sort(label2, new Sort());
to sort label2
, but I have no idea how to sort label1
in exaclty the same way (using label2
objects). Here is my Comparator
class:
class Sort implements Comparator<JLabel>{
public int compare(JLabel o1, JLabel o2) {
Double a = Double.parseDouble(o1.getText());
Double b = Double.parseDouble(o2.getText());
return b.compareTo(a);
}
}
Any ideas?
Given that you have no relationship defined between the two lists I think you should consider wrapping the two values up in a class:
class Foo {
private String name;
private double rating;
public Foo(String name, double rating){
this.name = name;
this.rating = rating;
}
// getters & setters
}
You can then have List<Foo>
and sort the list based on the value of rating.
In Java 8 this would be as simple as calling the sort()
method, which is now provided in List
, with a lambda expression passed in.
Let's solve this using a Map
. We'll first define a comparator to sort descending by value, like so:
class NumericComparator extends Comparator {
Map map;
public NumericComparator(Map map) {
this.map = map;
}
public int compare(Object o1, Object o2) {
return ((Integer) map.get(o2)).compareTo((Integer) map.get(o1));
}
}
We'll define the name as the key, and the rating as the value. Like so:
Map<String, Double> carMap = new HashMap<>();
//we can populate the map like so:
carMap.put("John", 10d); //works nicely in loops
Then we take that unsorted map, and insert all of it's values into a TreeMap
, that implements the NumericComparator
we defined earlier.
NumericComparator nc = new NumericComparator(carMap);
Map<String, Double> sortedMap = new TreeMap(nc);
sortedMap.putAll(carMap);
First, please program to the List
interface. Next, I'm assuming you can use apache libraries, there is Pair<L, R>
in apache commons-lang (or you could implement your own tuple class; or use another like this one ). Regardless, you'll need to modify your Comparator
to operate on the right-hand side (and I personally like to use the left-hand side to break ties). Finally, if you want to use label1
and label2
you'll need to copy the values back (after sorting). Something like,
List<JLabel> label1 = new ArrayList<>();
List<JLabel> label2 = new ArrayList<>();
// ...
List<Pair<JLabel, JLabel>> pairs = new ArrayList<>();
int len = label1.size();
if (len == label2.size()) {
for (int i = 0; i < len; i++) {
pairs.add(Pair.of(label1.get(i), label2.get(i)));
}
Collections.sort(pairs, new Comparator<Pair<JLabel, JLabel>>() {
@Override
public int compare(Pair<JLabel, JLabel> o1,
Pair<JLabel, JLabel> o2) {
double a = Double.parseDouble(o1.getRight().getText());
double b = Double.parseDouble(o2.getRight().getText());
int ret = Double.compare(a, b);
if (ret != 0) {
return ret;
} // if ret is 0, it's a tie.
return o1.getLeft().getText()
.compareTo(o2.getLeft().getText());
}
});
// ... only if you need to use label1 and label2 after the sort.
for (int i = 0; i < len; i++) {
label1.set(i, pairs.get(i).getLeft());
label2.set(i, pairs.get(i).getRight());
}
}
Good question -- and also a hassle for me when sorting player order by dice-throw in a board game app.
The previous answer of binding the two lists within a new gross object or in a map (when all the strings are unique) is fine.
But if you do want something simpler then here is this.
I was originally doing this without referencing a deep copy of the original comparison list and it was getting some of the sorting right and some odd entries mixed in . . . Eventually I saw the light and made a deep copy (label11) of the original list. Also ensure to put the sorting code into a private method so as to enable access to the two lists, label11 & label2, by the sort Comparator's overriding compare(..) method.
. . . .
. . . .
ArrayList<JLabel> label1 = new ArrayList<JLabel>(); // String list
ArrayList<JLabel> label2 = new ArrayList<JLabel>(); // Double list
System.out.println("Original String list : " + label1); // Check original list
sortByValue(label1, label2); // Sort label1 by label2 order descending
System.out.println("Sorted String list: " + label1); // Check sorted list
. . . .
. . . .
/** Private static method to facilitate access to list being sorted and
* the list used as a sort criterion by the code in the sort Comparator's
* overriding compare(..) method. */
private static void sortByValue(ArrayList<JLabel> label1,
ArrayList<JLabel> label2)
{
ArrayList<JLabel> label11 =
new ArrayList<JLabel>(label1); // Deep copy original string list
Collections.sort(list1, new Comparator<JLabel>()
{
@Override
public int compare(JLabel x, JLabel y)
{
return // Sort by descending label2 values
(Double.parseDouble(label2.get(label11.indexOf(y)).getText())
-Double.parseDouble(label2.get(label11.indexOf(x)).getText()))
.intValue();
}
});
}
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.