I have an issue with sorting an Array List. In a class i have two Array Lists of different objects, we can call the objects Foo and Bar.
public class Foo() {
int value;
//Some other fields, and setters and getters.
}
public class Bar() {
int id;
//Same here...
}
So the list fooList can be totally scrambeled. Say that i have 16 Foos, but Foo with value 5 can be on index 13 and so on.
What i'm trying to do is to order barList to match fooList after these values. If Foo with value 5 is on index 13, i want Bar with value 5 to be on index 13. My last attempt was this, but no success.
HashMap<Integer, Integer> positions = new HashMap<>();
for(int i=0;i<fooList.size();i++){
positions.put(foo.get(i).getValue, i);
}
Collections.sort(barList, new Comparator<Bar>(){
public int compare(Bar obj1, Bar obj2){
return positions.get(barList.indexOf(obj1)) -
positions.get(barList.indexOf(obj2));
}
});
Does anybody have a clue how to do this in an efficient way?
I'm not sure why you are using the index of an element in barList
to look into the map positions
.
This should help you
Collections.sort(barList, new Comparator<Bar>() {
@Override
public int compare(Bar o1, Bar o2) {
return positions.get(o1.getId()) - positions.get(o2.getId());
}
});
This can be simplified with a one-liner
Collections.sort(barList, Comparator.comparingInt(bar -> positions.get(bar.getId())));
Basically, the problem boils down to this:
Given two lists of integers A = {a 1 , a 2 ...a n } and B = {b 1 , b 2 , ...b m }, sort the list B based on the position of occurrence of the element in the first list, A.
For two elements x , y in B
So, the comparator function for Bar
has to compare the position at which a particular element has appeared in Foo
(based on the above).
NOTE: This assumes (as you have said) that there is no element in Bar
that is not there in Foo
. (The elements in Bar
are a subset of the elements in Foo
).
I'd first index items of the barList
on values so that it would be possible to quickly find a Bar
instance with the appropriate value. Then use it to transform the fooList
into the new barList
. Something along the lines:
Map<Integer, Bar> barMap = barList
.stream()
.collect(Collectors
.toMap(
Bar::getValue,
Function.identity());
barList = fooList
.stream()
.map(Foo::getValue)
.map(barMap::get)
.collect(Collectors.toList());
I think this must be as optimal as it gets in terms of time. In the expence of memory, you have to build a barMap
here.
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.