【问题标题】:Comparing lists of different types比较不同类型的列表
【发布时间】:2014-12-24 19:07:21
【问题描述】:

我有两个列表如下

List<MyObject1> list1
List<Long> list2

list2 基本上是 MyObject1 的 Id 列表,它是对象中的一个属性

Public Class MyObject1 implements Serializable{

    private Long myObjId;
     .....
      .....
      //other elements go here

   public Long getMyObjId() {
    return myObjId;
    }

    public void setMyObjId(Long myObjId) {
    this.myObjId = myObjId;
}

我想比较两个列表来检查list1中的所有对象是否都包含在list2中

一种方法是遍历 list1,从中创建一个新的 Id 列表,然后对其使用 containsAll 方法。

有没有更简单的方法可以达到同样的效果?

【问题讨论】:

  • 这是 Java 8 还是 Java 7 及更低版本?
  • @markspace 因为 lambdas
  • 可能需要更多详细信息。当 list2 包含 (1,2,3) 并且 list1 包含 ID 为 (1,2,2,3) 的对象时,检查是否应该返回“true”?无论如何,创建 ID 列表是可行且简单的,但根据确切的前提条件和要求,可能会有更优雅的解决方案。
  • 我使用的是 java 7,是的,如果 list1 包含 (1,2,3) 并且 list2 是 (1,2,2,3),它应该是正确的。基本上 list2 包含 list1 中的所有内容以及其他任何内容。
  • 我的问题是相反的(但可能没有重复的 ID,正如名称“ID”所暗示的......)

标签: java collections


【解决方案1】:

在 Java 8 中,您可以编写您所描述的内容:“一种方法是遍历 list1,从中创建一个新的 Id 列表,然后对其使用 containsAll 方法。”在一行中:

list1.stream().map(a -> a.getMyObjId()).collect(Collectors.toList()).containsAll(list2);

map 通过调用 a.getMyObjectId 将每个 MyObeject 转换为 id,collect 创建一个列表 结果。

【讨论】:

  • "... 检查 list1 中的所有对象是否都包含在 list2" - 你的 sn-p 是不是正好相反?
  • 那么反过来:list2.containsAll(...)。 sn -p 应该是如何实现一行转换的。
  • 我没有使用 Java 8 :(
  • 或 Collectors.toSet 以提高效率? :)
【解决方案2】:

至少有两种概念上不同的方法:

  • 可以收集列表中的 ID,然后处理结果列表
  • 可以即时进行检查

第一个可以归结为类似

boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
    List<Long> ids = new ArrayList<Integer>();
    for (MyObject m : myObjects) ids.add(m.getID());
    return validIds.continsAll(ids);
}

第二个可以写成

boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
    for (MyObject m : myObjects) {
        if (!validIds.contains(m.getID()) {
            return false;
        }
    }
    return true;
}

请注意,两种情况下的方法签名是相同的,因此您可以根据需要随意更改实现。特别是,如果validIds 的列表很大,那么首先将其转换为Set 会更有效。 (List 上的 contains 方法是 O(n),而在 Set 上是 O(1))。然后该方法可以实现为

boolean allIdsContained(List<MyObject> myObjects, List<Long> validIds) {
    Set<Long> set = new HashSet<Long>(validIds);
    for (MyObject m : myObjects) {
        if (!set.contains(m.getID()) {
            return false;
        }
    }
    return true;
}

无论如何,所有这些方法都可以用 Java 8 Lambda 更简洁地编写,但我认为这应该是一个实现细节,无论它是如何实现的,都应该隐藏在这样的辅助方法中。

【讨论】:

  • 我认为 OP 已经尝试过了,因为:他提到:“一种方法是遍历 list1,从中创建一个新的 Id 列表,然后在其上使用 containsAll 方法。 "
  • 更正我,但我认为他正在寻找一种更简单的方法来实现此解决方案..
  • 我想指出,有一个替代解决方案可以在不创建新列表的情况下工作,并且可能具有更好的性能,但也试图强调几乎没有“更简单”的解决方案,如果例如,“更简单”不仅意味着使用 lambda 使其更简洁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
  • 1970-01-01
  • 2022-06-16
  • 2015-04-20
  • 2019-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多