Sorting an arraylist based on objects value in another arraylist in Java

不想你离开。 提交于 2019-12-24 01:00:01

问题


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?


回答1:


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 = {a1, a2...an} and B = {b1, b2, ...bm}, 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

  • x > y, if x appears before y in A.
  • x < y, if x appears after y in A.
  • x = y, if x = y

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).




回答2:


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.



来源:https://stackoverflow.com/questions/49034985/sorting-an-arraylist-based-on-objects-value-in-another-arraylist-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!