【问题标题】:How can I return the difference between two lists?如何返回两个列表之间的差异?
【发布时间】:2015-01-16 03:31:46
【问题描述】:

我有两个数组列表,例如

List<Date> a;
contains : 10/10/2014, 10/11/2016

List<Date> b;
contains : 10/10/2016

如何在列表 ab 之间进行检查,以便返回 b 中缺少的值?例如10/10/2014

【问题讨论】:

  • guava 有一些不同的工具,但它适用于Set,我认为removeAll 可能适合你
  • 复制列表a。从副本中删除所有出现在b 中的元素。
  • 如果你想要两者之间的析取,CollectionUtil 有一个析取方法可以返回差值。
  • 这可能是指来自 Apache Commons Collections 的 CollectionUtils.subtract;有关详细信息,请参阅this answer

标签: java list object filtering


【解决方案1】:

您可以将它们转换为Set 集合,并对它们执行集差操作。

像这样:

Set<Date> ad = new HashSet<Date>(a);
Set<Date> bd = new HashSet<Date>(b);
ad.removeAll(bd);

【讨论】:

  • removeAll 返回 boolean 而不是 Set
  • 没错,但是当您查看文档时,您会看到此布尔值告知“此集合是否因调用而更改”。进行此更改后,您可以访问 Set,您会注意到它具有您预期的结果。
  • 创建bd HashSet 是不必要的。您可以拨打ad.removeAll(b)
  • 如果 bd 的元素比 ad 多怎么办?在那种情况下会发生什么?
【解决方案2】:

如果你只想找到b中的缺失值,你可以这样做:

List toReturn = new ArrayList(a);
toReturn.removeAll(b);

return toReturn;

如果您想找出任一列表中存在的值,您可以执行上面的代码两次。使用更改的列表。

【讨论】:

  • 如果它的列表不可修改怎么办?
  • 由于您创建了一个新列表,这也适用于不可修改的列表。
【解决方案3】:

我看起来很相似,但我想要两个列表中的差异(两个列表之间的不常见元素)。

假设我有:

List<String> oldKeys = Arrays.asList("key0","key1","key2","key5");
List<String> newKeys = Arrays.asList("key0","key2","key5", "key6");

我想知道添加了哪个键以及删除了哪个键,即我想获得(key1, key6)

使用org.apache.commons.collections.CollectionUtils

List<String> list = new ArrayList<>(CollectionUtils.disjunction(newKeys, oldKeys));

结果

["key1", "key6"]

【讨论】:

  • 你能不能把我指向 maven 存储库。我试过这个https://mvnrepository.com/artifact/org.apache.commons/commons-collections4/4.4 但它似乎不是正确的。
  • 非常感谢!!知道在新版本的包中重命名的函数是什么吗?
【解决方案4】:

您可以在 Java 8 Stream 库中使用 filter

List<String> aList = List.of("l","e","t","'","s");
List<String> bList = List.of("g","o","e","s","t");

List<String> difference = aList.stream()
    .filter(aObject -> {
        return ! bList.contains(aObject);
      })
    .collect(Collectors.toList());

//more reduced: no curly braces, no return
List<String> difference2 = aList.stream()
    .filter(aObject -> ! bList.contains(aObject))
    .collect(Collectors.toList());

System.out.println(difference); 的结果:

[e, t, s]

【讨论】:

  • 谢谢陌生人!
【解决方案5】:

您可以使用 Apache Commons Collections 4.0 中的 CollectionUtils:

new ArrayList<>(CollectionUtils.subtract(a, b))

【讨论】:

  • 注意:这种方法不以任何方式支持泛型,所以你得到的是一个原始的、未经检查的 Collection 实例。
  • 方法签名是:public static &lt;O&gt; Collection&lt;O&gt; subtract(Iterable&lt;? extends O&gt; a, Iterable&lt;? extends O&gt; b),根据文档:“O - 能够表示两个输入集合中包含的类型的泛型类型。”
  • 你确实是对的;过失。我正在查看该类的 3.2 版本,其中该方法具有简单的 public static Collection subtract(final Collection a, final Collection b) 签名。很高兴看到他们在 4.0 迭代中对此进行了改进。
【解决方案6】:

首先将列表转换为集合。

// create an empty set 
Set<T> set = new HashSet<>(); 

// Add each element of list into the set 
for (T t : list) 
    set.add(t); 

您可以使用 Sets.difference(Set1, Set2),它返回 Set1 中存在的额外项目。
您可以使用Sets.difference(Set2, Set1),它会返回 Set2 中存在的额外项目。

【讨论】:

  • 哇,不错的解决方案。我从来不知道这门课
【解决方案7】:

使用 Stream API,您可以执行以下操作:

List<String> aWithoutB = a.stream()
    .filter(element -> !b.contains(element))
    .collect(Collectors.toList());

List<String> bWithoutA = b.stream()
    .filter(element -> !a.contains(element))
    .collect(Collectors.toList());

【讨论】:

    【解决方案8】:

    这里是这个问题的通用解决方案。

    public <T> List<T> difference(List<T> first, List<T> second) {
        List<T> toReturn = new ArrayList<>(first);
        toReturn.removeAll(second);
        return toReturn;
    }
    

    【讨论】:

    • 这在大多数情况下都会派上用场。谢谢!!
    【解决方案9】:
    List<String> l1 = new ArrayList<String>();
    l1.add("apple");
    l1.add("orange");
    l1.add("banana");
    l1.add("strawberry");
    
    List<String> l2 = new ArrayList<String>();
    l2.add("apple");
    l2.add("orange");
    
    System.out.println(l1);
    System.out.println(l2);
    
    for (String A: l2) {
      if (l1.contains(A))
        l1.remove(A);
    }
    
    System.out.println("output");
    System.out.println(l1);
    

    输出:

    [apple, orange, banana, strawberry]
    [apple, orange]
    output
    [banana, strawberry]
    

    【讨论】:

      【解决方案10】:

      您可以在underscore-java 库中调用Underscore.difference(lists) 方法。 Live example

      import com.github.underscore.Underscore;
      import java.util.Arrays;
      import java.util.List;
      
      public class Main {
          public static void main(String[] args) {
              List<Integer> list1 = Arrays.asList(1, 2, 3);
              List<Integer> list2 = Arrays.asList(1, 2);
              List<Integer> list3 = Underscore.difference(list1, list2);
              System.out.println(list3);
              // [3]
          }
      }
      

      【讨论】:

      • 如果 list2 还包含一些额外的值怎么办。 list2 = {1,2,4,5}。预期列表 3 = {3,4,5}
      【解决方案11】:

      我一直在寻找一个不同的问题并遇到了这个问题,所以我将把我的解决方案添加到一个相关的问题:比较两个地图。

          // make a copy of the data
          Map<String,String> a = new HashMap<String,String>(actual);
          Map<String,String> e = new HashMap<String,String>(expected);
          // check *every* expected value
          for(Map.Entry<String, String> val : e.entrySet()){
              // check for presence
              if(!a.containsKey(val.getKey())){
                  System.out.println(String.format("Did not find expected value: %s", val.getKey()));
              }
              // check for equality
              else{
                  if(0 != a.get(val.getKey()).compareTo(val.getValue())){
                      System.out.println(String.format("Value does not match expected: %s", val.getValue()));
                  }
                  // we have found the item, so remove it 
                  // from future consideration. While it 
                  // doesn't affect Java Maps, other types of sets
                  // may contain duplicates, this will flag those
                  // duplicates. 
                  a.remove(val.getKey());
              }
          }
          // check to see that we did not receive extra values
          for(Map.Entry<String,String> val : a.entrySet()){
              System.out.println(String.format("Found unexpected value: %s", val.getKey()));
          }
      

      它的工作原理与其他解决方案相同,但不仅比较存在的值,而且比较它们包含相同的值。在比较来自两个来源的数据(员工和经理输入的值匹配;客户和公司交易匹配;...等)时,我主要在会计软件中使用它

      【讨论】:

      • 我不知道有关地图的问题。如果您发现有关地图的问题,请随时链接到此答案。
      • 答案应解决所提出的问题。如果您认为您有一个有用的代码 sn-p / 解释某些不存在问题的东西,请自己提出问题并使用内置的站点功能自行回答。不要在不相关的问题下发布您的答案。
      • 我的回答和问题的区别不在于Map vs List的使用。不同之处在于仅要求缺失值的问题,我解决了值的“缺失、添加和相等”。如果寻求答案的人看不到 MapSetList 是相关概念的方式,我会担心。
      【解决方案12】:

      Set 是下面的一个映射,我能够获得两个列表之间的差异,超过一百万个条目,每个条目都将其包装在一个 HashSet 中,这是一个简单的代码。

      private List<String>notPresentMethod(final List<String>left,final List<String>right){
          final Set<String>setIsFaster = new HashSet<>(right);
          return left.stream()
                  .filter(((Predicate<String>)setIsFaster::contains).negate())
                  .collect(Collectors.toList());
      }
      

      仅使用列表需要一个多小时,但没有完成。使用此示例只需几秒钟。

      【讨论】:

        猜你喜欢
        • 2011-01-05
        • 1970-01-01
        • 1970-01-01
        • 2011-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-28
        相关资源
        最近更新 更多