【问题标题】:Sorting an arraylist based on objects value in another arraylist in Java基于Java中另一个arraylist中的对象值对arraylist进行排序
【发布时间】:2018-02-28 17:07:00
【问题描述】:

我在对数组列表进行排序时遇到问题。 在一个类中,我有两个不同对象的数组列表,我们可以将对象称为 Foo 和 Bar。

public class Foo() {
   int value;
   //Some other fields, and setters and getters.
}

public class Bar() {
   int id;
   //Same here...
}

所以列表 fooList 可以完全打乱。假设我有 16 个 Foo,但值为 5 的 Foo 可以在索引 13 上,依此类推。

我要做的是在这些值之后命令 barList 与 fooList 匹配。 如果值为 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));
    }
});

有人知道如何以有效的方式做到这一点吗?

【问题讨论】:

  • 创建一个可比较的类FooBar。它包含对Foo 的引用和对Bar 的引用。根据您的标准,它与其他 FooBar 实例相当。
  • 那么将两个列表从 0 排序到限制呢?它对你有用吗?
  • 不应该positions.get( obj1.getId() )吗?
  • 你能解释一下当 Foo (value) 和 Bar (id) 值不相交时的预期行为吗?
  • 换句话说 - Bar 可以有一个 Foo 中不存在的 id 吗?

标签: java sorting arraylist


【解决方案1】:

我不确定您为什么要使用 barList 中的元素索引来查看地图 positions

这应该对你有帮助

Collections.sort(barList, new Comparator<Bar>() {
    @Override
    public int compare(Bar o1, Bar o2) {
        return positions.get(o1.getId()) - positions.get(o2.getId());
    }
});

这可以用一条线来简化

Collections.sort(barList, Comparator.comparingInt(bar -> positions.get(bar.getId())));

基本上,问题归结为:

给定两个整数列表 A = {a1, a2...an} 和 B = {b1, b2, ...bm},根据元素在第一个列表A中出现的位置对列表B进行排序.

对于两个元素xy在B

  • x > y,如果 x 在 A 中出现在 y 之前。
  • x ,如果 x 出现在 A 中的 y 之后。
  • x = y,如果 x = y

因此,Bar 的比较器函数必须比较特定元素在 Foo 中出现的位置(基于上述)。

注意:这假设(如您所说)Bar 中没有Foo 中不存在的元素。 (Bar 中的元素是Foo 中元素的子集。

【讨论】:

  • 你能解释一下为什么这是解决方案吗?
  • @EmilSundvall 你确定 Foo 没有任何 value 不在 Bar (Bar.id) 中。另外,请确保 Bar 列表中没有空值。
【解决方案2】:

我首先将barList 的项目索引到值上,以便可以快速找到具有适当值的Bar 实例。然后使用它将fooList 转换为新的barList。类似的东西:

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());

我认为这在时间上必须是最佳的。为了内存,你必须在这里建立一个barMap

【讨论】:

    猜你喜欢
    • 2017-09-17
    • 2018-04-21
    • 2014-11-09
    • 2017-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    相关资源
    最近更新 更多