简体   繁体   English

基于Java中另一个数组列表中的对象值对数组列表进行排序

[英]Sorting an arraylist based on objects value in another arraylist in Java

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.在一个类中,我有两个不同对象的数组列表,我们可以调用对象 Foo 和 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.所以列表 fooList 可以完全打乱。 Say that i have 16 Foos, but Foo with value 5 can be on index 13 and so on.假设我有 16 个 Foo,但值为 5 的 Foo 可以在索引 13 上,依此类推。

What i'm trying to do is to order barList to match fooList after these values.我想要做的是在这些值之后命令 barList 匹配 fooList。 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.如果值为 5 的 Foo 在索引 13 上,我希望值为 5 的 Bar 在索引 13 上。我最后一次尝试是这样,但没有成功。

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 .我不确定您为什么使用barList元素的索引来查看地图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.给定两个整数列表 A = {a 1 , a 2 ...a n } 和 B = {b 1 , b 2 , ...b m },根据其中元素出现的位置对列表 B 进行排序第一个列表,A。

For two elements x , y in B对于 B 中的两个元素x , y

  • x > y , if x appears before y in A. x > y ,如果x在 A 中出现在y之前。
  • x < y , if x appears after y in A. x < y ,如果x在 A 中出现在y之后。
  • x = y , if x = y x = y ,如果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).因此, Bar的比较器函数必须比较特定元素在Foo中出现的位置(基于上述)。

NOTE: This assumes (as you have said) that there is no element in Bar that is not there in Foo .注意:这假设(如您所说) Bar中没有Foo没有的元素 (The elements in Bar are a subset of the elements in Foo ). Bar中的元素是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.我首先在值上索引barList项目,以便可以快速找到具有适当值的Bar实例。 Then use it to transform the fooList into the new barList .然后使用它将fooList转换为新的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.为了内存,你必须在这里建立一个barMap

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM